-commit 1517ad263ba4c0b8c9251a726cce1ed8a86a634c
+commit 45f50ad3a8ce69c708974711a5939c42a74bf53b
Author: Bdale Garbee <bdale@gag.com>
-Date: Tue Jun 24 21:54:30 2014 -0600
+Date: Tue Sep 9 23:22:58 2014 -0600
- releasing 1.4.1
+ releasing version 1.5
-commit 6986da4407ac53e267b95abb1848211ea9d32b41
-Merge: 5f6059a 237472e
+commit a8c799c48a52bf13466536db627b66bfe2a435cd
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Sep 9 09:38:03 2014 -0700
+
+ altoslib/altosuilib: clean all versions of the .jar file
+
+ When we switch libary versions, we want to remove the old ones; just
+ have 'make clean' remove all versions of the libaries.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cef3be371cb3a9e481c2bd6abdf22c51953773f1
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Sep 9 09:37:13 2014 -0700
+
+ altoslib/altosuilib: Add EasyMega support
+
+ This makes flashing find the right files, and Monitor Idle show all of
+ the state data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08a82617c53718055d97df4fa60f3e5051d65383
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Sep 9 09:09:22 2014 -0700
+
+ altos/easymega: Set USB PID for EasyMega to 0x0028
+
+ It was using 0x0023, which is for TeleMega. 0x0028 is what's listed in
+ usbvidpid.h.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9d3ab4c78f79d659ce800def77bc441c95fa15be
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Sep 9 09:02:51 2014 -0700
+
+ altoslib: Fix idle monitor parsing of MMA655x state
+
+ There's no ':' after 'MMA655X value' in the output, and the parser
+ returns 'true' on success, not false.
+
+ With this, 'Monitor Idle' now reports correct accelerometer readings.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2b7ba0a5be70ae1d661afb2592ce8a6bf660c793
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Sep 9 09:01:42 2014 -0700
+
+ Tag version 1.4.9.3
+
+ This should be the final firmware version for 1.5
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 445d61c3810154193aebbf0f08f075ac8e107baf
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 6 22:56:25 2014 -0700
+
+ altosui: Include EasyMega firmware in fat release
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f0d2d34f84980ab45ecedae17546f4d71e020c5e
+Merge: 8c212cd 6c812f1
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sat Sep 6 23:42:47 2014 -0600
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 6c812f10761ec4ebf13e29ccef1d6c2c864f1158
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 6 22:28:13 2014 -0700
+
+ doc: Update for version 1.5 release
+
+ Add stuff about EasyMega and telemetry rate configuration. Update
+ screen shots as needed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d83afa9320c24056469984873af0a3c70bee0962
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 6 20:44:30 2014 -0700
+
+ altos: Scale packet master receive delay by baud rate
+
+ Increase the time we wait for return packets based on the remote
+ protocol baud rate.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e7515e3a88d53c50dd9b962cc8f43ce5376ccd0b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 6 20:43:32 2014 -0700
+
+ altoslib: Increase timeouts when using low baud rate remote protocol
+
+ When using 2400 or 9600 baud remote link rates, we need to increase
+ the packet timeout from 500ms to much longer values to avoid annoying
+ the user with timeout warnings.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 46f08f8709c538f3fee8e166598f0bb930df6e3c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 6 20:41:58 2014 -0700
+
+ altoslib: Update local callsign/baud rate when using remote protocol
+
+ We've had code to synchronously update the local and remote radio
+ frequencies when doing configuration over the remote link. This patch
+ adds the same code when changing the call sign and baud rate.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f395bcaa620490954d4a42de9b4870bc12bedc91
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 6 20:39:37 2014 -0700
+
+ altos: Reduce deviation at 2400/9600 baud
+
+ There's no reason to use 20.5kHz deviation at 2400 and 9600 baud, and
+ if we get a better receiver, we'll want to use narrower deviation to
+ have less bandwidth sucking noise into the radio. The new values are
+ (nominally) 5.125kHz deviation for 9600 baud and 1.5kHz deviation for
+ 2400 baud.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8c212cd5bfa03f71a31d84bd0051314e77d88461
+Merge: e9714e3 dd26ec2
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sat Sep 6 13:41:36 2014 -0600
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+ Conflicts:
+ ao-bringup/turnon_telemega
+
+commit e9714e34091abe657aa1b30aeda9466331aa39c1
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sat Sep 6 13:40:59 2014 -0600
+
+ tweaking test scripts
+
+commit dd26ec2e706bdd29090759deeb90090a0e3b74f0
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 6 00:39:41 2014 -0700
+
+ altosdroid: Mark completed items as 'done'
+
+ Frequency display
+ Re-load data on restart
+ Auto re-connect to TBT at correct freq
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 18671803d078aa798b603c67b741c3ba4374f41d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 6 00:14:26 2014 -0700
+
+ altosdroid: Add imperial unit support
+
+ Provides a menu entry to switch units, changes all value displays to
+ use the AltosLib units conversion code.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2b2ebd2fee46158abd1ae050cd6d1040ead849a0
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 5 23:10:07 2014 -0700
+
+ altosdroid: Update tab contents before switching
+
+ Make sure the new tab contents are updated before switching tabs so
+ that the user doesn't see old stuff.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08bbb1c3de73c9aaf920b11247eae544df6eac0c
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 5 22:06:21 2014 -0700
+
+ altosdroid: Ignore TelemetryService messages after service shutdown
+
+ Messages may get delivered after the service has been shut down;
+ ignore those.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 101ac21f05a69bdeb07d423aa18017eca04fc47f
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Sep 4 11:28:40 2014 -0700
+
+ altosdroid: add new TelemetryState.java
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2b03aca995b0151d7e820775f6a9d4afec462633
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 3 22:59:09 2014 -0700
+
+ altosui: Don't mark altimeter dirty when opening pyro panel
+
+ Skip setting the UI dirty when filling in the pyro firing time value.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit be38fb88d11bda1ba1caca38220773d3abcede19
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 3 22:58:22 2014 -0700
+
+ altos: Allow negative values for pyro configuration data
+
+ All of the integer pyro configuration parameters may be negative, so
+ parse that correctly.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3842735e303f0bf6f46ed8cb659c92d8bb9bd137
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 3 22:32:49 2014 -0700
+
+ altosdroid: Use single object to pass data to UI
+
+ Instead of having separate messages for each piece of telemetry state,
+ package the whole mess up in one object and send it for any
+ change. This simplifies tracking within the UI by avoiding corner
+ cases during reconnect.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit adc46e2f1346d98ef4f6c2351fef95fbc8ddf831
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 3 22:12:15 2014 -0700
+
+ altos/telefire: Add firing length to manual pad command
+
+ This adds an optional length of time (in 1/10s of a second) to the
+ ao_pad_manual function to enable testing of igniters without needing
+ to use TeleLCO.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b838a974d0dad43ff02060d8d913d9369eb20e96
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Sep 1 18:25:00 2014 -0500
+
+ altosui: Fix 'pad' screen for TeleGPS
+
+ Don't report pad position for TeleGPS
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7735cee871d02215517cb9d91cd552f003ca6a50
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Sep 1 18:23:42 2014 -0500
+
+ altoslib: Catch a couple null pointers in AltosConfigTD
+
+ When messing with TD, I hit a couple of paths that could try to
+ dereference null pointers. Check for those.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 57f0ae384f3c206ea777dc7c93b594ae3901f354
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Sep 1 18:21:49 2014 -0500
+
+ altoslib: Ignore extra AO_LOG_FLIGHT records from TeleGPS
+
+ TeleGPS was inserting a spurious AO_LOG_FLIGHT record each time it
+ turned on, which confused altoslib quite a bit.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a4202b4180e77e2a39ca071d3b8b8256ff0fc7b5
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Sep 1 18:12:29 2014 -0500
+
+ altos: Don't add AO_LOG_FLIGHT to existing GPS logs
+
+ When appending to a TeleGPS log, don't stick another flight value into
+ the log. That just confuses the ground station software.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aa7dd289ee72f7a49a08ce0229c4e0e0404499d0
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 31 00:28:15 2014 -0500
+
+ altosdroid: reload previous log file at connect time
+
+ Use the saved logfile to re-load the previous state at startup time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 00a3eace5ea885205270137f190538b010fd679f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 31 00:27:54 2014 -0500
+
+ altosdroid: Add missing preferences backend file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a5e348905a510bb2dcf6d7734f5681fb8338cd87
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 31 00:11:28 2014 -0500
+
+ altoslib: create logfiles preference object. check link in existing_data
+
+ The logfiles preference hash wasn't getting created, resulting in
+ crashes.
+
+ When there was no link, don't try to load existing data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bc3fbcb35090be3856284ccf4d908ebf39d02bec
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 31 00:08:33 2014 -0500
+
+ altosdroid: Add quit. Restart. Show freq in title.
+
+ Add a quit button to menu.
+ When restarting, reconnect to previous device.
+ When connecting, set the freq/rate to previous values.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0b70ea04e807c69a987d5976ab217f9f65fb1e09
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Aug 29 22:33:36 2014 -0500
+
+ altosdroid: fixup fetching active device address
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0014addf3356bad1eff76cffc396fb120308646c
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Aug 29 22:08:43 2014 -0500
+
+ altoslib: TeleMega telemetry pyro voltages are uint8
+
+ Using int8 means that voltages over about 6V are reported incorrectly.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 810f9a4f79b0480973d84595140d3f8948ce26d9
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Aug 29 15:22:43 2014 -0500
+
+ altosdroid: start restoring from log data on startup
+
+ Remember which flight was last being received and reload that file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5872bd10df14b47de0e541bff16d9220af0558aa
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Aug 29 15:12:38 2014 -0500
+
+ altos: Make sure pyro remains valid during delay
+
+ Keep checking pyro status while waiting for delay to expire to make
+ sure nothing changes. Disable pyro channel if something does.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 54994d02a5ca5bb91512f31748a48a0140d3a640
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 28 19:52:30 2014 -0700
+
+ ao-bringup: Test EasyMega boards
+
+commit 3c9cb4836edd4811fcdbb6ebbd25eb507a2ef5b1
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 18 10:57:26 2014 -0700
+
+ ao-bringup: Use ao-cal-accel instead of cal-accel in turnon scripts
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fac03ae9762f2af95b1ce5d99894173f9d9146f0
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 18 10:53:04 2014 -0700
+
+ Add ao-tools/ao-cal-accel
+
+ This C version may be more reliable than the nickle version
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b357544dd64f5b0f209c6cc6cb4fa392a2c3e1fa
Author: Bdale Garbee <bdale@gag.com>
-Date: Tue Jun 24 21:31:53 2014 -0600
+Date: Mon Aug 18 11:25:32 2014 -0600
+
+ turn echo back on after accel cal in turnon_telemetrum so rest is easier
+
+commit 44e389c31e5958c1a050fbe0dce5d7971a9d6a86
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 21:03:12 2014 -0700
+
+ altos: Add telerepeat-v1.0
+
+ This uses TeleBT hardware to provide a telemetry repeater, receiving
+ packets on one frequency and re-transmitting them on another.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5a51efd7f9b49ffadc91ccaf7a0d69566301c009
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 26 16:29:37 2014 -0700
+
+ altosui: Make Windows java test "smarter"
+
+ Or at least have it try more options, and then finally ask the user
+ before downloading and installing java
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bb7522acf040f41740ecd059e3d5d2480b652420
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:59:45 2014 -0700
+
+ telegps-v1.0: Provide one log and append to it
+
+ Instead of creating per-flight logs, create a single log and append
+ data to it each time TeleGPS is powered on. This avoids potentially
+ running out of log space just because the device is powered off/on.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1530c24cc75cdf9ba87c7e153ff28bf7beb4384c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:57:16 2014 -0700
+
+ cc1111: Wait for internal flash write to complete
+
+ This ensures that we don't try to start another write too soon.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 80e20b241359452028298567c76b2f644da5ad23
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:56:22 2014 -0700
+
+ Use -ldl when testing whether -m32 and -m64 builds work
+
+ We only need -ldl, and not -lbluetooth now that libaltos uses dlopen
+ on the bluetooth library
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 830f31fd6dc280e7a63ba689b7a48beff5c49072
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:55:34 2014 -0700
+
+ ao-tools/ao-send-telem: Support sending TM v2 and Tm v2 telemetry
+
+ Add state tracking so the telemetry sending code works.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 629b29b2718c174be9c811f224d0acf73fba4aff
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:54:44 2014 -0700
+
+ altoslib: Remove some debug printfs
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef1dd370564b99da033109f2fb5f7bf29711a13f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:53:31 2014 -0700
+
+ altoslib: Improve performance of AltosLib.hexbytes
+
+ On an android device, this function was spending quite a bit of time
+ calling hexbyte. Open code the conversion to improve performance.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ee9f68ec877e3e5a67179f8c8abafbccc80eb804
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:51:36 2014 -0700
+
+ altoslib: Close serial port when AltosFlash fails to detect a target
+
+ AltosDebug.check_connection raises an exception when the link fails,
+ but the AltosFlash constructor didn't close the serial port in this
+ case, causing the serial port to appear to be busy.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 76fd424e4624cb376ac2cf84b01b77599756680a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:50:38 2014 -0700
+
+ altoslib: Handle link timeout in AltosDebug.read_memory
+
+ link.get_reply returns null on a link error; don't crash in
+ read_memory when this happens.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 935f769fee351545622e223a283fca64608ca410
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:49:27 2014 -0700
+
+ altoslib: Parse 'Log fixed:' configuration value
+
+ TeleGPS holds a single flight record and constantly appends data to it
+ instead of having separate flight records on the board. It reports
+ 'Log fixed: 1' to let AltosLib know that the size of the per-flight
+ log is not configurable.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 59dfe661fcb504f390d9726378c676f2b5b005f3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:48:23 2014 -0700
+
+ altosdroid: Skip updating hidden UI elements
+
+ Instead of updating everything in the UI, only update the visible UI
+ elements to save a bunch of computation.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b1f1844aa514893228080704da3b3ccf855bda1e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 17 20:46:48 2014 -0700
+
+ altosdroid: Add telemetry rate support
+
+ Provides a menu to select the receiver telemetry bit rate
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e935ebe55705cb0506aac0859583d54fd8e5ca46
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 14 19:03:29 2014 -0700
+
+ altos: Report additional pyro channels via beeper
+
+ Send a beep for each additional pyro channel, low for no igniter, mid
+ for igniter. Does not change the reporting for the apogee/main channels.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c4dd29fcbbb93e991993a0aa444748dba4ee7dde
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jul 22 14:18:06 2014 -0700
+
+ altos: Document which TeleFire alarm pins are which
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d8e2b661e895fc59ded002a02191dcccce75f548
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 19 22:35:30 2014 -0700
+
+ altos: Have MicroKite just start recording at startup
+
+ This avoids having MicroKite try to detect boost and has it just start
+ recording data immediately.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 59976c44d1b6ee6505cfa4efd9a26ec4302f6c33
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Aug 14 18:16:14 2014 -0600
+
+ change easymega from v0.1 to v1.0, tweak to build on master, add to Makefile
+
+commit 4828be0ca5252ac9cd6061209385dcd6c4c57965
+Merge: 17e894d 165b7dc
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Aug 14 17:08:36 2014 -0600
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 165b7dcf6fba90b15ff32b891cba4b9111c1965b
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 16 17:13:25 2014 -0700
+
+ altoslib: Handle TeleGPS files for KML export
+
+ TeleGPS files had state values that couldn't be converted to colors,
+ which resulted in a truncated file that wasn't much use for anything.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 17e894d1b65231d07df009bc4e8ca92864ccf790
+Author: Bdale Garbee <bdale@gag.com>
+Date: Tue Jul 15 23:15:50 2014 -0600
+
+ update turnon tools
+
+commit ec7ceb607f5ba7e1ed5cfd32b7a452a5f364b095
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jul 15 00:44:14 2014 -0700
+
+ linux-fat: Fix up fat linux install icons, mime types and .desktop files
+
+ use the standard xdg utilities to install mime type and .desktop
+ files. The standard xdg icon installer doesn't handle svg icons, so we
+ have to do those manually.
+
+ With this patch, xfce, gnome3 and kde4 all place the applications in
+ user-visible menus, display correct file icons and launch correct
+ applications for our file types.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fb914d37018a585a879161483609d3c0be556d1e
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jul 14 02:32:03 2014 -0700
+
+ altosuilib: Fix minor scan UI nits
+
+ Wasn't computing geometry correctly and overlapped the 2400 baud entry
+ with the list of scan results.
+
+ Was not saving the telemetry rate/telemetry style when switching to
+ monitor mode, which caused the new monitor to come up with the wrong values.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 54b58e925e27e87bf2903678f87b7544ee2e8167
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jul 14 00:46:41 2014 -0700
+
+ Set version to 1.4.9.2
+
+commit 9e9151c3b4bb9ce329e1b44440a7aceb9f39b9a0
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jul 14 00:45:13 2014 -0700
+
+ altoslib: Parse eeprom 'altitude-32' fields
+
+ This lets us tell if the altimeter supports 32-bit GPS altitudes in
+ the eeprom log.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0fd867f504dd7df62e95da98ded511bb7b9e4c66
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jul 13 20:44:39 2014 -0700
+
+ altos/test: Build TeleMetrumV2 flight test variant
+
+ Parses TeleMetrumV2 eeprom files and runs the TeleMetrumV2 flight code.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 50aec54bdc35962145eff9b465f9cd7b3d9fea0b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jul 13 20:43:27 2014 -0700
+
+ altos: Make ao_gps_print deal with telem containing 32-bit altitude values
+
+ ao_gps_print is used with new telem packets from a few places; use
+ AO_TELEMETRY_LOCATION_ALTITUDE when necessary.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6c3d09bf40f2af6e8722f33a70b41e5d94ceaf9f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jul 13 20:42:41 2014 -0700
+
+ altos: Interrupt radio receive when changing data rate
+
+ This aborts any pending radio receive when changing the data rate so
+ that the radio can be reprogrammed to receive at the correct rate.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5d1adc6775a66633661af747bc4176e06f97630f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jul 13 20:41:36 2014 -0700
+
+ ao-tools: Add a few GPS telem/eeprom constants
+
+ These make it possible to encode/decode GPS data from telemetry and
+ eeprom files
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6c9daa4f471ac90ffce3bfe8876c9008f79a5b7f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jul 13 20:40:40 2014 -0700
+
+ ao-tools: Provide altitude to temperature conversion function
+
+ This takes altitude and computes the 'normal' temperature for
+ that.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e447e1e5c90d3fc1be9c5a1c966c7c688a87ba18
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jul 13 11:06:29 2014 -0700
+
+ ao-tools: Add TMv2 and Tgps log formats to cc.h
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a60ba449ec237ad3b8dade9dcea603b349dbccb1
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 12 23:52:05 2014 -0700
+
+ altos/telefire,telelco: Add HAS_RADIO_RATE to launch system software
+
+ This lets us set the rate to a lower value to improve range. 9600 baud
+ works great; 2400 baud makes the initial search take a long time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fa155693282746861b227afd6cbccc83dfd1bbed
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 21:27:30 2014 -0700
+
+ telegps: Missing function in TeleGPSConfigUI
+
+ set_altitude_32 was added to the abstract class but not here.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 405626971b47d4d4031312232bf13ad3d4bace7f
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 21:13:49 2014 -0700
+
+ libaltos: typo in libaltos broke the build
+
+ When converting this to use dlopen, I mis-typed the name hci_read_remote_name
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5f5b03879d9daa68a56498b45ae87a804cb1926b
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 18:43:31 2014 -0700
+
+ altosui: Don't show bluetooth UI bits on mac/windows
+
+ This just confuses people into thinking that bluetooth is supported on
+ those machines.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aac3fdce54233993c91d326df3732a7c448ac54a
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 18:42:37 2014 -0700
+
+ libaltos: Bind to libbluetooth at runtime on demand
+
+ This lets us reliably start and run without libbluetooth present.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 59702e5ff8d0522b0aa9dcca863309eaafbcda09
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 17:27:43 2014 -0700
+
+ altoslib: Extend telemetry heights from 16 to 32 bits
+
+ Uses the GPS data and/or previous kalman data to compute the upper 16
+ bits of the truncated telemetry altitude value.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6dc58c63d202e918f16d5fbe9b188d422edcdd9c
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 17:26:19 2014 -0700
+
+ altosui: Fix the 'Graph' button on the landed tab
+
+ It hasn't been getting enabled since the state tabs were rewritten.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 013e9ccfbe76dc46e8c69ea314950bed83d9a39f
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 17:18:38 2014 -0700
+
+ altos: Use 32-bits for flight state data (alt/speed/accel)
+
+ Stores 32-bits for all of the flight parameters. Uses 64-bit
+ intermediates for kalman computation.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 31ae24b5da3e198e7555ea3768d3cbdec3a28a5f
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 17:15:09 2014 -0700
+
+ altos: Record pdop value in TeleMetrumV2 log
+
+ There's only one byte free, so we'll record the pdop value
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 47e62bb26984f6c84660c1d0451f77c2d6ad7e5a
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 17:13:09 2014 -0700
+
+ altos: Scale DOP values by 10 in GPS drivers
+
+ sky traq was scaling by 5, ublox was scaling by 100.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ed2a08c50d6b8ebcc8c1d2f15e73c1f2a1e25041
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 17:10:49 2014 -0700
+
+ altoslib: Handle wide GPS altitude values in eeprom and telemetry
+
+ Detect when the wider data is present and handle it correctly
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 34d5be68ca23e8beb05db9a480faef63ecc911d0
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 17:07:48 2014 -0700
+
+ altos: Extend GPS altitudes to at least 24 bits everywhere
+
+ Telemetry gets a special 'mode' flag indicating that 24-bit data is
+ present; log files get new data and log readers are expected to detect
+ that via the firmware version number.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0d044af0c5025a63026d05adcab68f265f179668
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 16:19:52 2014 -0700
+
+ altosuilib: Allow for unitless axes in graphs
+
+ DOP values have no units.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a2f44fa867b17a0f1c1ee9aa9b99ecaa102a361b
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 16:19:34 2014 -0700
+
+ altosuilib: Add GPS DOP values to info table
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 61cbad00b68d9f4f2fed7b76132433e263966952
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 16:19:17 2014 -0700
+
+ altosuilib: Add GPS DOP values to graph
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9dafabd77676e08da4067cd405b6f03bf8d8ff85
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 16:17:56 2014 -0700
+
+ altoslib: Ensure CSV output is consistent
+
+ Scan entire flight to figure out which columns to include before
+ outputing header or data. Limit data output to values which are valid.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b8fa4e9a077e8e04b922d0c434c139ad0a57ee66
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 16:15:52 2014 -0700
+
+ altoslib: Clean up GPS DOP support in AltosState
+
+ Parse out hdop/pdop/vdop from telem and eeprom. Deal with legacy
+ eeprom files that have dop/100 instead of dop/10 values.
+
+ Clear state DOP values to MISSING at startup
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6f2a4c610dfacbf500650db0eeeca6623bb49c5c
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jul 10 00:26:55 2014 -0700
+
+ micropeak/altosui/telegps: Fix icon file names
+
+ The icon file names are now structured to have an organization name
+ and application name component. This should avoid collisions with
+ other packages when the icon files are installed in a shared
+ directory, as on Linux. Within the Java .jar file, the new names need
+ to be correctly referenced or we won't find them.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1684291ba9a4f3bc2828e7b079ac27efcba6a163
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jul 8 23:47:09 2014 -0700
+
+ altos/telemini-v2.0: Enable beep config and radio rate config
+
+ use the smaller pa to altitude table to make room for the new code
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d926ccfbd4596eb3f981d2fcf8f6fc6ccc427db6
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jul 8 23:46:24 2014 -0700
+
+ altos: Add smaller pa to altitude table for TeleMini
+
+ TeleMini doesn't have space for the larger table, and the smaller one
+ isn't that much less accurate at lower altitudes.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1a55cbe1923280f7009c13d5eb5b2ccac89219c2
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jul 8 23:45:10 2014 -0700
+
+ altos/telemini-v2.0: Add memory decorations to new telemetry variables
+
+ This lets TeleMini-v2.0 compile.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 95f3a2825377bdb6737446df051c069d58f42d08
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jul 8 23:43:31 2014 -0700
+
+ altosui: Hide inactive altimeter configuration entries
+
+ Instead of disabling them, just hide them so that entries that do not
+ apply to a particular device won't get shown at all.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 78db9e350db104da87e0fe4b72aa41bf6cf45e1d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jul 6 20:10:21 2014 -0700
+
+ Bump version to 1.4.9.1 -- on the way to 1.5
+
+commit d1527a5457210eb914312cf8857bfb88982a8462
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jul 6 12:35:13 2014 -0700
+
+ Add support for the "kite" micropeak variant
+
+ This uses a 100m 'launch detect' altitude and logs data every 19.2s
+ instead of every .192s.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f02cc3eec53e9d703837dad55ec2e6625b192588
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 5 00:16:57 2014 -0700
+
+ telegps: Support variable telemetry rate
+
+ Add combo box to monitoring window and device configuration.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit efb86669b5a74f244e2218f3385db633c36208af
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jul 4 23:41:16 2014 -0700
+
+ altosui: Support telemetry data rates
+
+ Add combo box to flight UI and flight hardware configuration UIs
+ Add telemetry rate to the TD/TBT config dialog
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9557a24b02911a93d74ee29ce359e40266cb4fed
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jul 4 23:57:42 2014 -0700
+
+ altosuilib: Add telemetry rate to Scan UI
+
+ Let the user scan for multiple data rates as well as telemetry formats
+ and frequencies
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 55e6558fa7cb23fb1363a86c83fbd6abf67ea324
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:48:13 2014 -0700
+
+ altoslib: Support multiple telemetry rates
+
+ Altos now supports 2400 and 9600 baud in addition to the classic 38400
+ baud rate. Add support to altoslib for these as well
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 292cb8380b478542555b5f370e8252eafa2f74ac
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 5 00:04:06 2014 -0700
+
+ altos: Rework packet receive for cc1120
+
+ Instead of blocking on PQT, just set up the receiver to start going
+ and when the first bit interrupt comes in, grab the SPI bus if
+ possible and configure it for reception. This improves sensitivity in
+ the radio by a significant amount while making the code conceptually a
+ bit nicer.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e0ee2ac6bc68b73e13bf34fac3ffd4a3b79dce98
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:34:48 2014 -0700
+
+ altos: Add telemetry rate support to CC1120 driver
+
+ This supports the new 2400 and 9600 baud rates
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 91461251f3aa8e1b37a3456f8fb94ab16bc0bec2
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jul 4 23:42:30 2014 -0700
+
+ altos: Packet reception tuning for cc1120 driver
+
+ This adjusts the cc1120 receive parameters to increase sensitivity at
+ the expense of reporting many more invalid packets to the UI.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8935e29e5aa9c01cd00b275a35dd7b99c00980c3
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:41:20 2014 -0700
+
+ altos: Add 2400 and 9600 baud telemetry support to cc115l driver
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aba1703a1cff3da001d64bf2d15a591816e3350e
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:31:59 2014 -0700
+
+ altos/cc1111: Add 2400 and 9600 baud telemetry rate support
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c20ddde2f9eb0ad8dbb982e9d0cbe91639160a34
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:30:23 2014 -0700
+
+ altos/cc1111: Adjust receive parameters to improve sensitivity
+
+ This removes the packet quality test and carrier sense tests when
+ deciding whether to start decoding a packet. This lets more bad
+ packets through, but the CRC check catches those and now we're
+ regularly receiving packets down to -110 or even -112 dBm. Before this
+ change, we'd rarely see packets as low as -105dBm
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ea5887027e7a39da2b7d84a142d74950b7a24703
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 5 00:09:25 2014 -0700
+
+ altos: Call ao_telemetry_reset_interval when telemetry rate changes
+
+ This lets the radio code adjust the telemetry packet sending pattern
+ when the data rate changes.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 214a38eb2b084baec526aa42016eddb954038639
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:44:07 2014 -0700
+
+ altos: Add config support for 2400 and 9600 baud telemetry rates
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0605b5a1cdff5cfd71fc9ef3161a62d74a1124b4
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:42:10 2014 -0700
+
+ altos: Add defines for 2400 and 9600 baud telemetry rates
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f8567a7be7ccd5dcc57ab65e63efe45e62008127
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jul 4 23:26:57 2014 -0700
+
+ altos: Reduce configuration data telemetry to once per 5 seconds
+
+ This data is constant, so we don't need to send it very often. Once
+ every five seconds should be plenty.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 657d455a2fad36193e6b3a7037d9ba7f09ae1168
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:46:07 2014 -0700
+
+ altos: Use TeleMetrum v1.9 board for MegaDongle experiments
+
+ This configures the MegaDongle v0.1 directory to use the pin
+ assignments in TeleMetrum v1.9 boards.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 48508479b0f6f8d6e73db1cae8ee8acdaba022d8
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:45:01 2014 -0700
+
+ altos: Stop sticking cc1111 firmware in src directory
+
+ This just clutters src.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 500353ec83af0da7fce3d67f2707f4725b1f50ba
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jul 2 22:42:43 2014 -0700
+
+ altos: ao_rssi subsystem needs to use AO_LED_TYPE instead of uint8_t
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cb15cb8db5ef570b57f89d4e58734554542f99ff
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jul 4 23:22:20 2014 -0700
+
+ altosuilib: Remove debug printfs from map cache
+
+ Just annoying
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2e99ff2c99f5d4a2fa196507e794c690665ab39e
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jul 4 23:20:51 2014 -0700
+
+ altoslib: Preserve receiver_serial across state reset for new transmitter
+
+ When the transmitter serial or flight number changes, we re-init the
+ state information, but we want to preserve the receiver serial number
+ so that the log file has that in the name
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d6e64790287d684cb9b70c67fa270825932cc020
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 25 13:50:54 2014 -0700
+
+ altoslib: Disable telemetry while getting config data
+
+ We're seeing some log files created without a suitable -via- number
+ included. My hypothesis is that incoming telemetry is getting
+ interleaved with the configuration data containing the serial
+ number. This change simply disables telemetry while retrieving the
+ configuration data to try and keep that from happening.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
- Merge branch 'branch-1.4' of ssh://git.gag.com/scm/git/fw/altos into branch-1.4
+commit 98c3c3f7edd58358939f7dacf5b8f4c336712f5b
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jul 4 23:38:53 2014 -0700
+
+ altosui/telegps: Undo the frequency/telemetry menu changes
+
+ Using menus for these items isn't what we want; we want to show the
+ current value on the screen, which is what a combo box is for. Switch
+ back to those and remove the frequency and telemetry config from the
+ TeleGPS menu bar so that Mac OS X is happy.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 5f6059a9273dfe557145a9f620db81693f3bc27e
+commit 505c6a1f8b8d68fe6f74dcb4428c860157fae3de
Author: Bdale Garbee <bdale@gag.com>
-Date: Tue Jun 24 21:22:26 2014 -0600
+Date: Wed Jun 25 13:37:56 2014 -0600
- need the api key in Bdale's root too
+ note need to push the updated repo with production binaries during release
-commit 42fd93b67af396b0478e9e795026cf1a5312e5c9
+commit 75db560e2c9fbb2889db507acc93e889bf15bc2a
Author: Bdale Garbee <bdale@gag.com>
-Date: Tue Jun 24 21:12:59 2014 -0600
+Date: Tue Jun 24 22:43:04 2014 -0600
- make sure to use Google Maps API key for official builds
+ Windows sucks, hard .. make sure filenames are legal in .mdwn files
-commit 9a78df4ea121d1d3c14da2abae1a82c34121e13c
+commit 61ca8493566d5ea0da379970ab94f80a462dd368
Author: Bdale Garbee <bdale@gag.com>
-Date: Sun Jun 15 18:41:25 2014 -0600
+Date: Tue Jun 24 22:35:43 2014 -0600
- notes updated for TeleGPS and 1.4 release learnings
+ update Releasing file based on learnings from 1.4.1 release
-commit 237472e1b98283a82c674bb48c0347189d9d37bf
+commit 424112349d54bb6360403683f8012b83f49220be
Author: Keith Packard <keithp@keithp.com>
-Date: Tue Jun 24 20:15:38 2014 -0700
+Date: Tue Jun 24 20:57:29 2014 -0700
- altosuilib: Mark 'Configure AltosUI' window with maps key status
+ telegps: Disable tracker config when not available
- This lets us check a build to make sure it has a maps key
+ Tracker motion and interval were both left enabled even when the
+ device being configured didn't support them. Disable them like other
+ elements.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7427f8bac7b3743ce0ab990612bf7168b95e22f9
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 20:52:34 2014 -0700
+
+ altosui: Don't show the tracker motion value when switching units
+
+ The tracker value was left enabled when hidden; the logic for deciding
+ whether to update it with new information used only the enabled state,
+ not the visible state. Set both states when hiding it to keep things
+ more consistent
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 0da9cdfbeacbaed13615ca2daade372920299c4a
+commit 6cb5955ab5aa3b42a507c4a02812cb5569b8562b
Author: Keith Packard <keithp@keithp.com>
Date: Fri Jun 20 11:56:58 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 2bbbd2c22e32d4c40782a9f12657f1a385cc6bc7
+commit f95b0e03c75d09e8ff4dbf9083cd3c8a30fdc4e6
Author: Keith Packard <keithp@keithp.com>
Date: Fri Jun 20 11:51:11 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 9dbd752150875f1f9fc93063f66d2153ec15d935
+commit b2c5f7d10265794a5778546f2e3eca7d763eab56
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 20:31:50 2014 -0700
+
+ Clean all .desktop files, ignore them too
+
+ All .desktop files are built from .desktop.in files, so just remove
+ all of them in make clean, and ignore all of them in .gitignore.
+ This makes the rename less painful.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d1065424d144b8dab949db7e57140ffdf244bd48
+Author: Bdale Garbee <bdale@gag.com>
+Date: Tue Jun 24 21:22:26 2014 -0600
+
+ need the api key in Bdale's root too
+
+commit bd440afc2a6e37b74fffcf1b977e149485095316
+Merge: 5d4f912 a0ccab8
+Author: Bdale Garbee <bdale@gag.com>
+Date: Tue Jun 24 21:17:53 2014 -0600
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit a0ccab8e4235934538a03f8be3b37aa1bbd6b144
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 20:15:38 2014 -0700
+
+ altosuilib: Mark 'Configure AltosUI' window with maps key status
+
+ This lets us check a build to make sure it has a maps key
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5d4f912bcc6784f975c82f7b0ed8dc360e60aae8
+Author: Bdale Garbee <bdale@gag.com>
+Date: Tue Jun 24 21:12:59 2014 -0600
+
+ make sure to use Google Maps API key for official builds
+
+commit 048ce00ea0d1d2744552942559aa1da2431ab954
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 18:26:04 2014 -0700
+
+ icon: Generate altusmetrum.xpm and install it
+
+ This is for the debian menu, still a required part of a debian package.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit dbff6dd42f8b6fb90c8d3f07bde48a6be0bfddf0
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 18:25:31 2014 -0700
+
+ altosuilib: Outline map lines and distance value with white
+
+ This makes the value and line visible on dark backgrounds
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ade2cc9abb8ca403a9ae5d1f9c145ab72ce94919
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 18:24:02 2014 -0700
+
+ altosuilib: Make map cache size configurable
+
+ Systems with sufficient memory can get smoother map scrolling by
+ making the cache larger. Would be nice to do this automatically?
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 97269bb90c1602a1f8c54fc7b6c34383a0370621
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 15:58:35 2014 -0700
+
+ Bump version to 1.4.1.1
+
+commit 309d91d25099bebda21e165165efa9ce86cb0a47
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 15:57:13 2014 -0700
+
+ altos/ao_flight_test: Get the Tmega version compiling again
+
+ A few changes broke this recently.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 443bbb09468df7c1a10f2c76996c92380d8b8c23
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jun 24 15:56:11 2014 -0700
+
+ altos: Add optional debugging to print out pyro firing status
+
+ This dumps pyro check failures for ao_flight_test so you can see why
+ pyro charges aren't firing.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0a19073649570016db28d5e2a4a225273732adb5
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 22 21:13:54 2014 -0700
+
+ ao-bringup: Use the C tools to test EasyMini
+
+ I think my USB driver in the kernel is broken; the nickle versions of
+ these tools did very strange things and never worked.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fc3364de2b6cdfff53f5c38b3ae52ae5601ff3b7
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 22 21:12:37 2014 -0700
+
+ ao-tools: Add ao-test-baro, ao-test-igniter and ao-test-flash
+
+ C versions of the test programs used to validate hardware prior to ship
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6cc2d671c0e335fbedb0e97699f8f273502c6807
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 22 21:06:24 2014 -0700
+
+ altosui/telegps: Expose configurable APRS SSID
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3f3382126bf1122b1a78abe8458af5ec112a1f95
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jun 22 21:05:05 2014 -0700
+
+ altos: Make APRS SSID configurable
+
+ This uses the low-digit from the serial number by default, but lets
+ the user change it if desired.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ca1c62ca3ea016a1a5baa4520e484c102280c3e3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jun 21 18:27:42 2014 -0700
+
+ altosui: Add Ignitor tab to Monitor Idle mode
+
+ Oops; missed adding this when I included it in the Monitor Flight window.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 602d6a2424a5c16e22febf6b4e6b3816022261c7
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 20 00:41:17 2014 -0700
+
+ altos/aprs: Encode last serial number in SSID. Transmit serial in comment
+
+ This makes it a lot easier to tell which device is sending
+ information, and to receive data from multiple devices on the same
+ receiver.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3016ee5f21ec66bf9230b90ab1420b8fad628f8d
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jun 20 00:40:10 2014 -0700
+
+ altosuilib: Wrap radio frequency menu in JMenuBar when used in config
+
+ The device config dialogs place the radio frequency menu inside a
+ dialog box; it needs to be inside a MenuBar to work properly, so
+ create one to hold it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1b0f56ddb2b85b68232c22a7a8b8744cb9ad76f9
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 19 14:33:27 2014 -0700
+
+ Rename icon files to fit XDG specifications. Add file icons. Add mime types
+
+ Our SVG icons now follow XDG standards by including a vendor
+ prefix. The new file type icons include application-vnd.altusmetrum as
+ a prefix so that they match the mime types declared.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 37856672c57f2fd91184c2391a201bbbdc48545e
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jun 19 10:25:07 2014 -0700
+
+ linux: .desktop files must begin with organization name
+
+ The spec requires that .desktop files start with the organization
+ name, so I've renamed all of them to altusmetrum-<application>.desktop
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d773cb8921848c99f12b8cd9840cb0267b66e1f
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 18 20:35:12 2014 -0700
+
+ windows: Missed adding 'refresh-sh.nsh'
+
+ This script forces windows explorer to reload icons.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7767a045d446ea2bc5fe1ec98d89274155f956c4
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 18 16:18:05 2014 -0700
+
+ macosx: Respond to apple messages in all apps
+
+ This connects the callbacks in AltosUIFrame to actually do something
+ useful with them.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d5bdb1c5974788b9569897435808fd01b04b0c4d
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 18 16:14:44 2014 -0700
+
+ altosuilib: Hook up apple messages to callbacks
+
+ This supports open, quit and preferences. I'm leaving 'about' to the
+ existing stuff until I decide it's worth the effort to create a fancy
+ about dialog.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e3eab18682e77c5394918448409d383a28ba23ad
Author: Keith Packard <keithp@keithp.com>
Date: Wed Jun 18 14:16:36 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 44f60782d73bf5fdb6e1e54a3fdbe50808b7d7f5
+commit fac94c593285eacda57de257fa2be0548341b567
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 18 14:15:27 2014 -0700
+
+ macosx: Define icons for our file types on OS X
+
+ Adds definitions to the Info.plist files shipped to specify which
+ icons to show for .telem, .eeprom and .mpd files. Note that the
+ applications don't respond to open apple events, so double clicking on
+ a file only starts the application.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5871225a0c442cf5afa41a444ff8bfb8f4002721
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 18 02:16:51 2014 -0700
+
+ windows installer: Create file associations for Windows.
+
+ This makes icons appear for the files in the file manager, and lets
+ you double-click on the files to open the appropriate application.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c93c4efefee0dbf6d193466efd6761d9a1849ae9
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Jun 18 02:15:04 2014 -0700
+
+ icon: Construct .exe files to hold windows icons for file associations
+
+ It appears that creating an executable with an icon resource is the
+ only way to display icons for files. Fortunately, that's not all that
+ hard.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3f4e765c05ddbae83ca0c0176572cd698f285d08
Author: Keith Packard <keithp@keithp.com>
Date: Tue Jun 17 20:46:33 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 7140ca8a4bc0be8386f8edacadb7ac5d88c6f1b1
+commit 495e84540943cccb6d1cb965a772021f7dc5f639
Author: Keith Packard <keithp@keithp.com>
Date: Tue Jun 17 00:08:03 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
+commit b397e4ff45f054acb1347ffa5468950febc431f7
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 16 23:03:49 2014 -0700
+
+ altos/micropeak: Add load script template
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c8078d352a7f54a4a97d25af080155d3f875536a
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 16 22:49:34 2014 -0700
+
+ java: Bump java library versions for next release
+
+ Prepare for future release by bumping java versions now
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 75766b0e7ee30fb3bfbf90ecb68f7758bac6eeba
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 16 22:48:25 2014 -0700
+
+ altosui: Fix ground station configure frequency list
+
+ Fix the API to match the switch to a menu, wrap in a menu bar to make
+ it work.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ed38b1b596062b2232fa78a3181f6eaf5818b651
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 16 21:58:13 2014 -0700
+
+ altosuilib: Move menu bars into the Mac OS X top bar
+
+ Setting these properties causes the top menu bar to get placed into
+ the Mac OS X window system menu bar
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e612693e33ef3b0e22db0656792992fa6e961ff2
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 16 21:57:35 2014 -0700
+
+ altosui/telegps: Use menus for frequency list and telemetry formats
+
+ This will let us move them into the Mac OS X menu bar, as well as
+ making them look a bit nicer.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6579e4cae8fea65780f1c4677f29c1fc17ca41e2
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 16 15:59:09 2014 -0700
+
+ altos/micropeak: Create a script to load firmware.
+
+ The micropeak-load script flashes micropeak with firmware from
+ whatever directory it is sitting in. A 'publish' target in the source
+ directory copies the script and hex to ~/altusmetrumllc/Binaries
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 31beeb0882d27cbc05e28118611feec4ae43d9da
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jun 16 11:02:49 2014 -0700
+
+ doc: Add instructions for flash recovery technique
+
+ The flash recovery section explained which pins to connect, but lacked
+ explicit instructions on how to make it work.
+
+commit f167d348b147e89d269ad35806e39f28cf104afb
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jun 15 18:41:25 2014 -0600
+
+ notes updated for TeleGPS and 1.4 release learnings
+
commit 9ab3a1de95b705783c31a7e16447f52c10b6b480
Author: Bdale Garbee <bdale@gag.com>
Date: Sun Jun 15 17:44:42 2014 -0600
cd libaltos && $(MAKE) all
cd altoslib && $(MAKE) all
cd altosuilib && $(MAKE) all
+ cd icon && $(MAKE) fat
cd altosui && $(MAKE) fat
cd micropeak && $(MAKE) fat
cd telegps && $(MAKE) fat
These are Bdale's notes on how to do a release.
+ - make sure build environment is up to date
+ sudo cowbuilder --update
+
git checkout master
- make sure the Google Maps API key is in the build chroot and root
src/telemetrum-v2.0/flash-loader/*.elf \
~/altusmetrumllc/Binaries/loaders/
(cd ~/altusmetrumllc ; git add Binaries ; git commit -a)
+ (cd ~/altusmetrumllc ; git push)
- copy the relevant release notes file from doc/ to
/home/bdale/web/altusmetrum/AltOS/releases/<rev>
- go edit ~/web/altusmetrum/AltOS/releases/<rev>.mdwn,
/home/bdale/web/altusmetrum/MicroPeak/releases/<rev>.mdwn, and
- /home/bdale/web/altusmetrum/TeleGPS/releases/<rev>.mdwn, to
- include release date and explicit ref to dir contents so the
- web pages shows versioned links, commit and push
+ /home/bdale/web/altusmetrum/TeleGPS/releases/<rev>.mdwn
+
+ - make sure the Windows stuff is like 1-4-1, not 1.4.1!
(cd doc ; make publish)
*) Highlight current frequency in the frequency list.
+ Placed current frequency in title bar
+
*) Random frequency selection. Provide some mechanism to input
arbitrary radio frequencies. Could be like AltosUI which allows
you to edit the list of frequencies and assign names to them,
*) Remember most-recently-used TBT and frequency, perhaps
auto-connect at startup.
+
+ Done
*) Re-loading flight data from .telem file to get back to
'find my rocket' mode after shutting down the application.
+ Done
+
*) Imperial Units mode
+ Done
+
*) TeleBT battery voltage
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <TextView android:id="@+id/title_paired_devices"
+ <Button android:id="@+id/button_scan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/title_paired_devices"
+ android:text="@string/button_scan"
+ />
+ <TextView android:id="@+id/title_new_devices"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/title_other_devices"
android:visibility="gone"
android:background="#666"
android:textColor="#fff"
android:paddingLeft="5dp"
/>
- <ListView android:id="@+id/paired_devices"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:stackFromBottom="true"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/title_new_devices"
+ <TextView android:id="@+id/title_paired_devices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/title_other_devices"
+ android:text="@string/title_paired_devices"
android:visibility="gone"
android:background="#666"
android:textColor="#fff"
android:paddingLeft="5dp"
/>
- <ListView android:id="@+id/new_devices"
+ <ListView android:id="@+id/paired_devices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stackFromBottom="true"
- android:layout_weight="2"
+ android:layout_weight="1"
/>
- <Button android:id="@+id/button_scan"
+ <ListView android:id="@+id/new_devices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/button_scan"
+ android:stackFromBottom="true"
+ android:layout_weight="2"
/>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
<item android:id="@+id/connect_scan"
android:icon="@android:drawable/ic_menu_search"
android:title="@string/connect_device" />
+ <item android:id="@+id/quit"
+ android:icon="@android:drawable/ic_menu_close_clear_cancel"
+ android:title="@string/quit" />
<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" />
</menu>
<!-- AltosDroid -->
<string name="bt_not_enabled">Bluetooth was not enabled.</string>
<string name="title_connecting">connecting…</string>
- <string name="title_connected_to">connected: </string>
+ <string name="title_connected_to">connected</string>
<string name="title_not_connected">not connected</string>
<!-- Options Menu -->
<string name="connect_device">Connect a device</string>
+ <string name="quit">Quit</string>
<string name="select_freq">Select radio frequency</string>
+ <string name="select_rate">Select data rate</string>
+ <string name="change_units">Change units</string>
<!-- DeviceListActivity -->
<string name="scanning">scanning for devices…</string>
//import android.os.Message;
import android.util.Log;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosBluetooth extends AltosLink {
// Constructor
public AltosBluetooth(BluetoothDevice in_device, Handler in_handler) {
+// set_debug(D);
adapter = BluetoothAdapter.getDefaultAdapter();
device = in_device;
handler = in_handler;
}
}
+ public double frequency() {
+ return frequency;
+ }
+
+ public int telemetry_rate() {
+ return telemetry_rate;
+ }
+
+ public void save_frequency() {
+ AltosPreferences.set_frequency(0, frequency);
+ }
+
+ public void save_telemetry_rate() {
+ AltosPreferences.set_telemetry_rate(0, telemetry_rate);
+ }
+
private synchronized void wait_connected() throws InterruptedException, IOException {
if (input == null) {
+ if (D) Log.d(TAG, "wait_connected...");
wait();
+ if (D) Log.d(TAG, "wait_connected done");
if (input == null) throw new IOException();
}
}
} catch (InterruptedException e) {
connection_lost();
}
- }
+ }
+
+ private static final int buffer_size = 1024;
+
+ private byte[] buffer = new byte[buffer_size];
+ private int buffer_len = 0;
+ private int buffer_off = 0;
public int getchar() {
- try {
- wait_connected();
- return input.read();
- } catch (IOException e) {
- connection_lost();
- } catch (java.lang.InterruptedException e) {
- connection_lost();
+ while (buffer_off == buffer_len) {
+ try {
+ wait_connected();
+ buffer_len = input.read(buffer);
+ buffer_off = 0;
+ } catch (IOException e) {
+ connection_lost();
+ return AltosLink.ERROR;
+ } catch (java.lang.InterruptedException e) {
+ connection_lost();
+ return AltosLink.ERROR;
+ }
}
- return AltosLink.ERROR;
+ return buffer[buffer_off++];
}
public void close() {
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Window;
+import android.view.View;
import android.widget.TabHost;
import android.widget.TextView;
+import android.widget.RelativeLayout;
import android.widget.Toast;
import android.app.AlertDialog;
import android.location.Location;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
-public class AltosDroid extends FragmentActivity {
+public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
// Debugging
- private static final String TAG = "AltosDroid";
- private static final boolean D = true;
+ static final String TAG = "AltosDroid";
+ static final boolean D = true;
// Message types received by our Handler
- public static final int MSG_STATE_CHANGE = 1;
- public static final int MSG_TELEMETRY = 2;
- public static final int MSG_UPDATE_AGE = 3;
- public static final int MSG_LOCATION = 4;
- public static final int MSG_CRC_ERROR = 5;
+
+ public static final int MSG_STATE = 1;
+ public static final int MSG_UPDATE_AGE = 2;
// Intent request codes
- private static final int REQUEST_CONNECT_DEVICE = 1;
- private static final int REQUEST_ENABLE_BT = 2;
+ public static final int REQUEST_CONNECT_DEVICE = 1;
+ public static final int REQUEST_ENABLE_BT = 2;
+
+ public static FragmentManager fm;
+
+ private BluetoothAdapter mBluetoothAdapter = null;
// Layout Views
private TextView mTitle;
private TextView mRSSIView;
private TextView mSerialView;
private TextView mFlightView;
+ private RelativeLayout mStateLayout;
private TextView mStateView;
private TextView mAgeView;
// field to display the version at the bottom of the screen
private TextView mVersion;
+ private double frequency;
+ private int telemetry_rate;
+
// Tabs
TabHost mTabHost;
AltosViewPager mViewPager;
int tabHeight;
// Timer and Saved flight state for Age calculation
- private Timer timer = new Timer();
+ private Timer timer;
AltosState saved_state;
- Location saved_location;
// Service
private boolean mIsBound = false;
private Messenger mService = null;
final Messenger mMessenger = new Messenger(new IncomingHandler(this));
- // Preferences
- private AltosDroidPreferences prefs = null;
-
- // TeleBT Config data
- private AltosConfigData mConfigData = null;
- // Local Bluetooth adapter
- private BluetoothAdapter mBluetoothAdapter = null;
-
// Text to Speech
private AltosVoice mAltosVoice = null;
@Override
public void handleMessage(Message msg) {
AltosDroid ad = mAltosDroid.get();
+
switch (msg.what) {
- case MSG_STATE_CHANGE:
- if(D) Log.d(TAG, "MSG_STATE_CHANGE: " + msg.arg1);
- switch (msg.arg1) {
- case TelemetryService.STATE_CONNECTED:
- ad.mConfigData = (AltosConfigData) msg.obj;
- String str = String.format(" %s S/N: %d", ad.mConfigData.product, ad.mConfigData.serial);
- ad.mTitle.setText(R.string.title_connected_to);
- ad.mTitle.append(str);
- Toast.makeText(ad.getApplicationContext(), "Connected to " + str, Toast.LENGTH_SHORT).show();
- break;
- case TelemetryService.STATE_CONNECTING:
- ad.mTitle.setText(R.string.title_connecting);
- break;
- case TelemetryService.STATE_READY:
- case TelemetryService.STATE_NONE:
- ad.mConfigData = null;
- ad.mTitle.setText(R.string.title_not_connected);
- break;
+ case MSG_STATE:
+ if(D) Log.d(TAG, "MSG_STATE");
+ TelemetryState telemetry_state = (TelemetryState) msg.obj;
+ if (telemetry_state == null) {
+ Log.d(TAG, "telemetry_state null!");
+ return;
}
+
+ ad.update_state(telemetry_state);
break;
- case MSG_TELEMETRY:
- ad.update_ui((AltosState) msg.obj);
- break;
- case MSG_LOCATION:
- ad.set_location((Location) msg.obj);
- break;
- case MSG_CRC_ERROR:
case MSG_UPDATE_AGE:
- if (ad.saved_state != null) {
- ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.received_time + 500) / 1000));
- }
+ if(D) Log.d(TAG, "MSG_UPDATE_AGE");
+ ad.update_age();
break;
}
}
mTabs.remove(mTab);
}
- void set_location(Location location) {
- saved_location = location;
- update_ui(saved_state);
+ public void units_changed(boolean imperial_units) {
+ for (AltosDroidTab mTab : mTabs)
+ mTab.units_changed(imperial_units);
}
- void update_ui(AltosState state) {
- if (state != null && saved_state != null) {
- if (saved_state.state != state.state) {
- String currentTab = mTabHost.getCurrentTabTag();
- switch (state.state) {
- case AltosLib.ao_flight_boost:
- if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent");
- break;
- case AltosLib.ao_flight_drogue:
- if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent");
- break;
- case AltosLib.ao_flight_landed:
- if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed");
- break;
- }
+ void update_title(TelemetryState telemetry_state) {
+ switch (telemetry_state.connect) {
+ case TelemetryState.CONNECT_CONNECTED:
+ if (telemetry_state.config != null) {
+ String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial,
+ telemetry_state.frequency);
+ 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]));
+ mTitle.setText(str);
+ } else {
+ mTitle.setText(R.string.title_connected_to);
}
+ break;
+ case TelemetryState.CONNECT_CONNECTING:
+ mTitle.setText(R.string.title_connecting);
+ break;
+ case TelemetryState.CONNECT_READY:
+ case TelemetryState.CONNECT_NONE:
+ mTitle.setText(R.string.title_not_connected);
+ break;
}
- saved_state = state;
+ }
- AltosGreatCircle from_receiver = null;
+ void start_timer() {
+ if (timer == null) {
+ timer = new Timer();
+ timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 1000L);
+ }
+ }
+
+ void stop_timer() {
+ if (timer != null) {
+ timer.cancel();
+ timer.purge();
+ timer = null;
+ }
+ }
+
+ boolean registered_units_listener;
+
+ void update_state(TelemetryState telemetry_state) {
- if (state != null && saved_location != null && state.gps != null && state.gps.locked) {
- double altitude = 0;
- if (saved_location.hasAltitude())
- altitude = saved_location.getAltitude();
- from_receiver = new AltosGreatCircle(saved_location.getLatitude(),
- saved_location.getLongitude(),
- altitude,
- state.gps.lat,
- state.gps.lon,
- state.gps.alt);
+ if (!registered_units_listener) {
+ registered_units_listener = true;
+ AltosPreferences.register_units_listener(this);
}
+ update_title(telemetry_state);
+ update_ui(telemetry_state.state, telemetry_state.location);
+ if (telemetry_state.connect == TelemetryState.CONNECT_CONNECTED)
+ start_timer();
+ else
+ stop_timer();
+ }
+
+ boolean same_string(String a, String b) {
+ if (a == null) {
+ if (b == null)
+ return true;
+ return false;
+ } else {
+ if (b == null)
+ return false;
+ return a.equals(b);
+ }
+ }
+
+ void update_age() {
+ if (saved_state != null)
+ mAgeView.setText(String.format("%d", (System.currentTimeMillis() - saved_state.received_time + 500) / 1000));
+ }
+
+ void update_ui(AltosState state, Location location) {
+
+ Log.d(TAG, "update_ui");
+
+ int prev_state = AltosLib.ao_flight_invalid;
+
+ AltosGreatCircle from_receiver = null;
+
+ if (saved_state != null)
+ prev_state = saved_state.state;
+
if (state != null) {
- mCallsignView.setText(state.callsign);
- mSerialView.setText(String.format("%d", state.serial));
- mFlightView.setText(String.format("%d", state.flight));
- mStateView.setText(state.state_name());
- mRSSIView.setText(String.format("%d", state.rssi));
+ Log.d(TAG, String.format("prev state %d new state %d\n", prev_state, state.state));
+ if (state.state == AltosLib.ao_flight_stateless) {
+ boolean prev_locked = false;
+ boolean locked = false;
+
+ if(state.gps != null)
+ locked = state.gps.locked;
+ if (saved_state != null && saved_state.gps != null)
+ prev_locked = saved_state.gps.locked;
+ if (prev_locked != locked) {
+ String currentTab = mTabHost.getCurrentTabTag();
+ if (locked) {
+ if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent");
+ } else {
+ if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("pad");
+ }
+ }
+ } else {
+ if (prev_state != state.state) {
+ String currentTab = mTabHost.getCurrentTabTag();
+ Log.d(TAG, "switch state");
+ switch (state.state) {
+ case AltosLib.ao_flight_boost:
+ if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent");
+ break;
+ case AltosLib.ao_flight_drogue:
+ if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent");
+ break;
+ case AltosLib.ao_flight_landed:
+ if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed");
+ break;
+ case AltosLib.ao_flight_stateless:
+ if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent");
+ break;
+ }
+ }
+ }
+
+ if (location != null && state.gps != null && state.gps.locked) {
+ double altitude = 0;
+ if (location.hasAltitude())
+ altitude = location.getAltitude();
+ from_receiver = new AltosGreatCircle(location.getLatitude(),
+ location.getLongitude(),
+ altitude,
+ state.gps.lat,
+ state.gps.lon,
+ state.gps.alt);
+ }
+
+ if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) {
+ Log.d(TAG, "update callsign");
+ mCallsignView.setText(state.callsign);
+ }
+ if (saved_state == null || state.serial != saved_state.serial) {
+ Log.d(TAG, "update serial");
+ mSerialView.setText(String.format("%d", state.serial));
+ }
+ if (saved_state == null || state.flight != saved_state.flight) {
+ Log.d(TAG, "update flight");
+ mFlightView.setText(String.format("%d", state.flight));
+ }
+ if (saved_state == null || state.state != saved_state.state) {
+ Log.d(TAG, "update state");
+ if (state.state == AltosLib.ao_flight_stateless) {
+ mStateLayout.setVisibility(View.GONE);
+ } else {
+ mStateView.setText(state.state_name());
+ mStateLayout.setVisibility(View.VISIBLE);
+ }
+ }
+ if (saved_state == null || state.rssi != saved_state.rssi) {
+ Log.d(TAG, "update rssi");
+ mRSSIView.setText(String.format("%d", state.rssi));
+ }
}
for (AltosDroidTab mTab : mTabs)
- mTab.update_ui(state, from_receiver, saved_location);
+ mTab.update_ui(state, from_receiver, location, mTab == mTabsAdapter.currentItem());
if (state != null)
- mAltosVoice.tell(state);
+ mAltosVoice.tell(state, from_receiver);
+
+ saved_state = state;
}
private void onTimerTick() {
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
finish();
- return;
}
- // Initialise preferences
- prefs = new AltosDroidPreferences(this);
- AltosPreferences.init(prefs);
+ fm = getSupportFragmentManager();
// Set up the window layout
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
for (int i = 0; i < 5; i++)
mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = tabHeight;
-
// Set up the custom title
mTitle = (TextView) findViewById(R.id.title_left_text);
mTitle.setText(R.string.app_name);
mRSSIView = (TextView) findViewById(R.id.rssi_value);
mSerialView = (TextView) findViewById(R.id.serial_value);
mFlightView = (TextView) findViewById(R.id.flight_value);
+ mStateLayout = (RelativeLayout) findViewById(R.id.state_container);
mStateView = (TextView) findViewById(R.id.state_value);
mAgeView = (TextView) findViewById(R.id.age_value);
- timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 100L);
-
mAltosVoice = new AltosVoice(this);
}
super.onStart();
if(D) Log.e(TAG, "++ ON START ++");
+ // Start Telemetry Service
+ startService(new Intent(AltosDroid.this, TelemetryService.class));
+
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
+ startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT);
}
- // Start Telemetry Service
- startService(new Intent(AltosDroid.this, TelemetryService.class));
-
doBindService();
+
}
@Override
if(D) Log.e(TAG, "--- ON DESTROY ---");
if (mAltosVoice != null) mAltosVoice.stop();
+ stop_timer();
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
}
- private void connectDevice(Intent data) {
- // Get the device MAC address
- String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
- // Get the BLuetoothDevice object
- BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
+ private void connectDevice(String address) {
// Attempt to connect to the device
try {
- if (D) Log.d(TAG, "Connecting to " + device.getName());
- mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, device));
+ if (D) Log.d(TAG, "Connecting to " + address);
+ mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, address));
} catch (RemoteException e) {
}
}
+ private void connectDevice(Intent data) {
+ // Get the device MAC address
+ String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
+ connectDevice(address);
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
}
}
+ void setBaud(int baud) {
+ try {
+ mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
+ } catch (RemoteException e) {
+ }
+ }
+
+ void setBaud(String baud) {
+ try {
+ int value = Integer.parseInt(baud);
+ int rate = AltosLib.ao_telemetry_rate_38400;
+ switch (value) {
+ case 2400:
+ rate = AltosLib.ao_telemetry_rate_2400;
+ break;
+ case 9600:
+ rate = AltosLib.ao_telemetry_rate_9600;
+ break;
+ case 38400:
+ rate = AltosLib.ao_telemetry_rate_38400;
+ break;
+ }
+ setBaud(rate);
+ } catch (NumberFormatException e) {
+ }
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent serverIntent = null;
serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
return true;
+ case R.id.quit:
+ Log.d(TAG, "R.id.quit");
+ stopService(new Intent(AltosDroid.this, TelemetryService.class));
+ finish();
+ return true;
case R.id.select_freq:
// Set the TBT radio frequency
"Channel 9 (435.450MHz)"
};
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle("Pick a frequency");
- builder.setItems(frequencies,
+ AlertDialog.Builder builder_freq = new AlertDialog.Builder(this);
+ builder_freq.setTitle("Pick a frequency");
+ builder_freq.setItems(frequencies,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
setFrequency(frequencies[item]);
}
});
- AlertDialog alert = builder.create();
- alert.show();
+ 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;
}
return false;
/*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ * 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
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-
package org.altusmetrum.AltosDroid;
-import java.io.File;
-import java.util.Map;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Environment;
-
-import org.altusmetrum.altoslib_4.*;
-
-public class AltosDroidPreferences implements AltosPreferencesBackend {
- public final static String NAME = "org.altusmetrum.AltosDroid";
- private Context context = null;
- private SharedPreferences prefs = null;
- private SharedPreferences.Editor editor = null;
-
- public AltosDroidPreferences(Context in_context) {
- this(in_context, NAME);
- }
-
- public AltosDroidPreferences(Context in_context, String in_prefs) {
- context = in_context;
- prefs = context.getSharedPreferences(in_prefs, 0);
- editor = prefs.edit();
- }
-
- public String[] keys() {
- Map<String, ?> all = prefs.getAll();
- return (String[])all.keySet().toArray();
- }
-
- public AltosPreferencesBackend node(String key) {
- return new AltosDroidPreferences(context, key);
- }
-
- public boolean nodeExists(String key) {
- return prefs.contains(key);
- }
-
- public boolean getBoolean(String key, boolean def) {
- return prefs.getBoolean(key, def);
- }
-
- public double getDouble(String key, double def) {
- Float f = Float.valueOf(prefs.getFloat(key, (float)def));
- return f.doubleValue();
- }
-
- public int getInt(String key, int def) {
- return prefs.getInt(key, def);
- }
+import org.altusmetrum.altoslib_5.*;
- public String getString(String key, String def) {
- return prefs.getString(key, def);
- }
+public class AltosDroidPreferences extends AltosPreferences {
- public void putBoolean(String key, boolean value) {
- editor.putBoolean(key, value);
- }
+ /* Active device preference name */
+ final static String activeDevicePreference = "ACTIVE-DEVICE";
- public void putDouble(String key, double value) {
- editor.putFloat(key, (float)value);
- }
+ static String active_device_address;
- public void putInt(String key, int value) {
- editor.putInt(key, value);
- }
+ public static void init(Context context) {
+ if (backend != null)
+ return;
- public void putString(String key, String value) {
- editor.putString(key, value);
- }
+ AltosPreferences.init(new AltosDroidPreferencesBackend(context));
- public void remove(String key) {
- editor.remove(key);
+ active_device_address = backend.getString(activeDevicePreference, null);
}
- public void flush() {
- editor.apply();
+ public static void set_active_device(String address) {
+ synchronized(backend) {
+ active_device_address = address;
+ backend.putString(activeDevicePreference, active_device_address);
+ flush_preferences();
+ }
}
- public File homeDirectory() {
- return Environment.getExternalStorageDirectory();
+ public static String active_device() {
+ synchronized(backend) {
+ return active_device_address;
+ }
}
}
--- /dev/null
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.io.File;
+import java.util.Map;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Environment;
+
+import org.altusmetrum.altoslib_5.*;
+
+public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
+ public final static String NAME = "org.altusmetrum.AltosDroid";
+ private Context context = null;
+ private SharedPreferences prefs = null;
+ private SharedPreferences.Editor editor = null;
+
+ public AltosDroidPreferencesBackend(Context in_context) {
+ this(in_context, NAME);
+ }
+
+ public AltosDroidPreferencesBackend(Context in_context, String in_prefs) {
+ context = in_context;
+ prefs = context.getSharedPreferences(in_prefs, 0);
+ editor = prefs.edit();
+ }
+
+ public String[] keys() {
+ Map<String, ?> all = prefs.getAll();
+ return (String[])all.keySet().toArray();
+ }
+
+ public AltosPreferencesBackend node(String key) {
+ return new AltosDroidPreferencesBackend(context, key);
+ }
+
+ public boolean nodeExists(String key) {
+ return prefs.contains(key);
+ }
+
+ public boolean getBoolean(String key, boolean def) {
+ return prefs.getBoolean(key, def);
+ }
+
+ public double getDouble(String key, double def) {
+ Float f = Float.valueOf(prefs.getFloat(key, (float)def));
+ return f.doubleValue();
+ }
+
+ public int getInt(String key, int def) {
+ return prefs.getInt(key, def);
+ }
+
+ public String getString(String key, String def) {
+ return prefs.getString(key, def);
+ }
+
+ public void putBoolean(String key, boolean value) {
+ editor.putBoolean(key, value);
+ }
+
+ public void putDouble(String key, double value) {
+ editor.putFloat(key, (float)value);
+ }
+
+ public void putInt(String key, int value) {
+ editor.putInt(key, value);
+ }
+
+ public void putString(String key, String value) {
+ editor.putString(key, value);
+ }
+
+ public void remove(String key) {
+ editor.remove(key);
+ }
+
+ public void flush() {
+ editor.apply();
+ }
+
+ public File homeDirectory() {
+ return Environment.getExternalStorageDirectory();
+ }
+}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import android.location.Location;
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.app.FragmentManager;
+import android.location.Location;
+import android.util.Log;
+import android.widget.TextView;
+
+public abstract class AltosDroidTab extends Fragment implements AltosUnitsListener {
+ AltosState last_state;
+ AltosGreatCircle last_from_receiver;
+ Location last_receiver;
+
+ public abstract void show(AltosState state, AltosGreatCircle from_receiver, Location receiver);
+
+ public abstract String tab_name();
+
+ public void units_changed(boolean imperial_units) {
+ if (!isHidden() && last_state != null)
+ show(last_state, last_from_receiver, last_receiver);
+ }
+
+ public void set_value(TextView text_view,
+ AltosUnits units,
+ int width,
+ double value) {
+ if (value == AltosLib.MISSING)
+ text_view.setText("");
+ else
+ text_view.setText(units.show(width, value));
+ }
+
+ public void set_visible(boolean visible) {
+ FragmentTransaction ft = AltosDroid.fm.beginTransaction();
+ if (visible) {
+ AltosState state = last_state;
+ AltosGreatCircle from_receiver = last_from_receiver;
+ Location receiver = last_receiver;
+
+ show(state, from_receiver, receiver);
+ ft.show(this);
+ } else
+ ft.hide(this);
+ ft.commit();
+ }
+
+ public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver, boolean is_current) {
+ last_state = state;
+ last_from_receiver = from_receiver;
+ last_receiver = receiver;
+ if (is_current) {
+ if (AltosDroid.D) Log.d(AltosDroid.TAG, String.format("%s: visible, performing update", tab_name()));
-public interface AltosDroidTab {
- public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver);
+ show(state, from_receiver, receiver);
+ } else {
+ if (AltosDroid.D) Log.d(AltosDroid.TAG, String.format("%s: not visible, skipping update", tab_name()));
+ return;
+ }
+ }
}
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosVoice {
}
- public void speak(String s) {
+ public synchronized void speak(String s) {
if (!tts_enabled) return;
tts.speak(s, TextToSpeech.QUEUE_ADD, null);
}
}
}
- public void tell(AltosState state) {
+ public void tell(AltosState state, AltosGreatCircle from_receiver) {
if (!tts_enabled) return;
boolean spoke = false;
if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) &&
state.state > AltosLib.ao_flight_boost) {
if (state.max_speed() != AltosLib.MISSING)
- speak(String.format("max speed: %d meters per second.", (int) (state.max_speed() + 0.5)));
+ speak(String.format("Max speed: %s.",
+ AltosConvert.speed.say_units(state.max_speed())));
spoke = true;
} else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) &&
state.state >= AltosLib.ao_flight_drogue) {
if (state.max_height() != AltosLib.MISSING)
- speak(String.format("max height: %d meters.", (int) (state.max_height() + 0.5)));
+ speak(String.format("Max height: %s.",
+ AltosConvert.height.say_units(state.max_height())));
spoke = true;
}
}
}
}
old_state = state;
- idle_thread.notice(state, spoke);
+ if (idle_thread != null)
+ idle_thread.notice(state, from_receiver, spoke);
}
class IdleThread extends Thread {
boolean started;
private AltosState state;
+ private AltosGreatCircle from_receiver;
int reported_landing;
int report_interval;
long report_time;
return;
}
- /* If the rocket isn't on the pad, then report height */
- if (((AltosLib.ao_flight_drogue <= state.state &&
+ /* If the rocket isn't on the pad, then report location */
+ if ((AltosLib.ao_flight_drogue <= state.state &&
state.state < AltosLib.ao_flight_landed) ||
- state.state == AltosLib.ao_flight_stateless) &&
- state.range >= 0)
+ state.state == AltosLib.ao_flight_stateless)
{
- speak(String.format("Height %d, bearing %s %d, elevation %d, range %d.\n",
- (int) (state.height() + 0.5),
- state.from_pad.bearing_words(
- AltosGreatCircle.BEARING_VOICE),
- (int) (state.from_pad.bearing + 0.5),
- (int) (state.elevation + 0.5),
- (int) (state.range + 0.5)));
+ AltosGreatCircle position;
+
+ if (from_receiver != null)
+ position = from_receiver;
+ else
+ position = state.from_pad;
+
+ if (position != null) {
+ speak(String.format("Height %s, bearing %s %d, elevation %d, range %s.\n",
+ AltosConvert.height.say_units(state.height()),
+ position.bearing_words(
+ AltosGreatCircle.BEARING_VOICE),
+ (int) (position.bearing + 0.5),
+ (int) (position.elevation + 0.5),
+ AltosConvert.distance.say_units(position.range)));
+ }
} else if (state.state > AltosLib.ao_flight_pad) {
if (state.height() != AltosLib.MISSING)
- speak(String.format("%d meters", (int) (state.height() + 0.5)));
+ speak(AltosConvert.height.say_units(state.height()));
} else {
reported_landing = 0;
}
else
speak("rocket may have crashed");
if (state.from_pad != null)
- speak(String.format("Bearing %d degrees, range %d meters.",
+ speak(String.format("Bearing %d degrees, range %s.",
(int) (state.from_pad.bearing + 0.5),
- (int) (state.from_pad.distance + 0.5)));
+ AltosConvert.distance.say_units(state.from_pad.distance)));
++reported_landing;
}
}
}
}
- public synchronized void notice(AltosState new_state, boolean spoken) {
+ public synchronized void notice(AltosState new_state, AltosGreatCircle new_from_receiver, boolean spoken) {
AltosState old_state = state;
state = new_state;
+ from_receiver = new_from_receiver;
if (!started && state.state > AltosLib.ao_flight_pad) {
started = true;
start();
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
+import android.view.View;
public class GoNoGoLights {
private Boolean state;
missing = m;
set = true;
if (missing) {
+ hide();
red.setImageDrawable(dGray);
green.setImageDrawable(dGray);
} else if (state) {
red.setImageDrawable(dGray);
green.setImageDrawable(dGreen);
+ show();
} else {
red.setImageDrawable(dRed);
green.setImageDrawable(dGray);
+ show();
}
}
+
+ public void show() {
+ red.setVisibility(View.VISIBLE);
+ green.setVisibility(View.VISIBLE);
+ }
+
+ public void hide() {
+ red.setVisibility(View.GONE);
+ green.setVisibility(View.GONE);
+ }
}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.location.Location;
-public class TabAscent extends Fragment implements AltosDroidTab {
+public class TabAscent extends AltosDroidTab {
AltosDroid mAltosDroid;
private TextView mHeightView;
mAltosDroid = null;
}
- public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public String tab_name() {
+ return "ascent";
+ }
+
+ public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (state != null) {
- mHeightView.setText(AltosDroid.number("%6.0f m", state.height()));
- mMaxHeightView.setText(AltosDroid.number("%6.0f m", state.max_height()));
- mSpeedView.setText(AltosDroid.number("%6.0f m/s", state.speed()));
- mMaxSpeedView.setText(AltosDroid.number("%6.0f m/s", state.max_speed()));
- mAccelView.setText(AltosDroid.number("%6.0f m/s²", state.acceleration()));
- mMaxAccelView.setText(AltosDroid.number("%6.0f m/s²", state.max_acceleration()));
+ set_value(mHeightView, AltosConvert.height, 6, state.height());
+ set_value(mHeightView, AltosConvert.height, 6, state.height());
+ set_value(mMaxHeightView, AltosConvert.height, 6, state.max_height());
+ set_value(mSpeedView, AltosConvert.speed, 6, state.speed());
+ set_value(mMaxSpeedView, AltosConvert.speed, 6, state.max_speed());
+ set_value(mAccelView, AltosConvert.accel, 6, state.acceleration());
+ set_value(mMaxAccelView, AltosConvert.accel, 6, state.max_acceleration());
if (state.gps != null) {
mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.location.Location;
-public class TabDescent extends Fragment implements AltosDroidTab {
+public class TabDescent extends AltosDroidTab {
AltosDroid mAltosDroid;
private TextView mSpeedView;
mAltosDroid = null;
}
- public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public String tab_name() { return "descent"; }
+
+ public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (state != null) {
- mSpeedView.setText(AltosDroid.number("%6.0f m/s", state.speed()));
- mHeightView.setText(AltosDroid.number("%6.0f m", state.height()));
+ set_value(mSpeedView, AltosConvert.speed, 6, state.speed());
+ set_value(mHeightView, AltosConvert.height, 6, state.height());
if (from_receiver != null) {
mElevationView.setText(AltosDroid.number("%3.0f°", from_receiver.elevation));
- mRangeView.setText(AltosDroid.number("%6.0f m", from_receiver.range));
+ set_value(mRangeView, AltosConvert.distance, 6, from_receiver.range);
mBearingView.setText(AltosDroid.number("%3.0f°", from_receiver.bearing));
mCompassView.setText(from_receiver.bearing_words(AltosGreatCircle.BEARING_LONG));
- mDistanceView.setText(AltosDroid.number("%6.0f m", from_receiver.distance));
+ set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
} else {
mElevationView.setText("<unknown>");
mRangeView.setText("<unknown>");
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.location.Location;
-public class TabLanded extends Fragment implements AltosDroidTab {
+public class TabLanded extends AltosDroidTab {
AltosDroid mAltosDroid;
private TextView mBearingView;
mAltosDroid = null;
}
- public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public String tab_name() { return "landed"; }
+
+ public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (from_receiver != null) {
mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
- mDistanceView.setText(String.format("%6.0f m", from_receiver.distance));
+ set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
}
if (state != null && state.gps != null) {
mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
}
-
+
if (state != null) {
- mMaxHeightView.setText(String.format("%6.0f m", state.max_height()));
- mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration()));
- mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed()));
+ set_value(mMaxHeightView, AltosConvert.height, 6, state.max_height());
+ set_value(mMaxAccelView, AltosConvert.accel, 6, state.max_acceleration());
+ set_value(mMaxSpeedView, AltosConvert.speed, 6, state.max_speed());
}
}
-
}
import java.util.Arrays;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import android.widget.TextView;
import android.location.Location;
-public class TabMap extends Fragment implements AltosDroidTab {
+public class TabMap extends AltosDroidTab {
AltosDroid mAltosDroid;
private SupportMapFragment mMapFragment;
private Marker mRocketMarker;
private Marker mPadMarker;
+ private boolean pad_set;
private Polyline mPolyline;
private TextView mDistanceView;
}
}
- public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public String tab_name() { return "map"; }
+
+ public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (from_receiver != null) {
mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
- mDistanceView.setText(String.format("%6.0f m", from_receiver.distance));
+ set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
}
if (state != null) {
mPolyline.setVisible(true);
}
- if (state.state == AltosLib.ao_flight_pad) {
+ if (!pad_set && state.pad_lat != AltosLib.MISSING) {
+ pad_set = true;
mPadMarker.setPosition(new LatLng(state.pad_lat, state.pad_lon));
mPadMarker.setVisible(true);
}
}
}
-
}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.location.Location;
-public class TabPad extends Fragment implements AltosDroidTab {
+public class TabPad extends AltosDroidTab {
AltosDroid mAltosDroid;
private TextView mBatteryVoltageView;
+ private TextView mBatteryVoltageLabel;
private GoNoGoLights mBatteryLights;
private TextView mApogeeVoltageView;
+ private TextView mApogeeVoltageLabel;
private GoNoGoLights mApogeeLights;
private TextView mMainVoltageView;
+ private TextView mMainVoltageLabel;
private GoNoGoLights mMainLights;
private TextView mDataLoggingView;
private GoNoGoLights mDataLoggingLights;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tab_pad, container, false);
mBatteryVoltageView = (TextView) v.findViewById(R.id.battery_voltage_value);
+ mBatteryVoltageLabel = (TextView) v.findViewById(R.id.battery_voltage_label);
mBatteryLights = new GoNoGoLights((ImageView) v.findViewById(R.id.battery_redled),
(ImageView) v.findViewById(R.id.battery_greenled),
getResources());
mApogeeVoltageView = (TextView) v.findViewById(R.id.apogee_voltage_value);
+ mApogeeVoltageLabel = (TextView) v.findViewById(R.id.apogee_voltage_label);
mApogeeLights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
(ImageView) v.findViewById(R.id.apogee_greenled),
getResources());
mMainVoltageView = (TextView) v.findViewById(R.id.main_voltage_value);
+ mMainVoltageLabel = (TextView) v.findViewById(R.id.main_voltage_label);
mMainLights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
(ImageView) v.findViewById(R.id.main_greenled),
getResources());
mAltosDroid = null;
}
- public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public String tab_name() { return "pad"; }
+
+ public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (state != null) {
mBatteryVoltageView.setText(AltosDroid.number("%4.2f V", state.battery_voltage));
mBatteryLights.set(state.battery_voltage >= AltosLib.ao_battery_good, state.battery_voltage == AltosLib.MISSING);
-
- mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+ if (state.apogee_voltage == AltosLib.MISSING) {
+ mApogeeVoltageView.setVisibility(View.GONE);
+ mApogeeVoltageLabel.setVisibility(View.GONE);
+ } else {
+ mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+ mApogeeVoltageView.setVisibility(View.VISIBLE);
+ mApogeeVoltageLabel.setVisibility(View.VISIBLE);
+ }
mApogeeLights.set(state.apogee_voltage >= AltosLib.ao_igniter_good, state.apogee_voltage == AltosLib.MISSING);
-
- mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+ if (state.main_voltage == AltosLib.MISSING) {
+ mMainVoltageView.setVisibility(View.GONE);
+ mMainVoltageLabel.setVisibility(View.GONE);
+ } else {
+ mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+ mMainVoltageView.setVisibility(View.VISIBLE);
+ mMainVoltageLabel.setVisibility(View.VISIBLE);
+ }
mMainLights.set(state.main_voltage >= AltosLib.ao_igniter_good, state.main_voltage == AltosLib.MISSING);
if (state.flight != 0) {
}
if (receiver != null) {
- double altitude = 0;
+ double altitude = AltosLib.MISSING;
if (receiver.hasAltitude())
altitude = receiver.getAltitude();
mPadLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
mPadLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
- mPadAltitudeView.setText(AltosDroid.number("%4.0f m", altitude));
+ set_value(mPadAltitudeView, AltosConvert.height, 6, altitude);
}
}
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabWidget;
-
-
+import android.util.Log;
/**
* This is a helper class that implements the management of tabs and all
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+ private int position;
- static final class TabInfo {
+ static class TabInfo {
private final String tag;
private final Class<?> clss;
private final Bundle args;
+ private Fragment fragment;
TabInfo(String _tag, Class<?> _class, Bundle _args) {
tag = _tag;
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
- return Fragment.instantiate(mContext, info.clss.getName(), info.args);
+ Log.d(AltosDroid.TAG, String.format("TabsAdapter.getItem(%d)", position));
+ info.fragment = Fragment.instantiate(mContext, info.clss.getName(), info.args);
+ return info.fragment;
+ }
+
+ public Fragment currentItem() {
+ TabInfo info = mTabs.get(position);
+ return info.fragment;
}
public void onTabChanged(String tabId) {
- int position = mTabHost.getCurrentTab();
+ AltosDroidTab prev_frag = (AltosDroidTab) mTabs.get(position).fragment;
+
+ position = mTabHost.getCurrentTab();
+
+ AltosDroidTab cur_frag = (AltosDroidTab) mTabs.get(position).fragment;
+
+ if (prev_frag != cur_frag) {
+ if (prev_frag != null) {
+ prev_frag.set_visible(false);
+ }
+ }
+ if (cur_frag != null) {
+ cur_frag.set_visible(true);
+ }
+ Log.d(AltosDroid.TAG, String.format("TabsAdapter.onTabChanged(%s) = %d", tabId, position));
mViewPager.setCurrentItem(position);
}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.util.Log;
import android.os.Handler;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class TelemetryReader extends Thread {
private static final String TAG = "TelemetryReader";
+ private static final boolean D = true;
int crc_errors;
AltosLink link;
AltosState state = null;
+ AltosFlightReader stacked;
+
LinkedBlockingQueue<AltosLine> telemQueue;
public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException {
public void close() {
state = null;
+ if (stacked != null) {
+ stacked.close(false);
+ stacked = null;
+ }
link.remove_monitor(telemQueue);
link = null;
telemQueue.clear();
AltosState state = null;
try {
- for (;;) {
+ if (D) Log.d(TAG, "starting reader");
+ while (stacked != null) {
+ AltosState stacked_state = null;
+ try {
+ stacked_state = stacked.read();
+ } catch (ParseException pe) {
+ continue;
+ } catch (AltosCRCException ce) {
+ continue;
+ }
+ if (stacked_state != null)
+ state = stacked_state;
+ else
+ stacked = null;
+ }
+ if (state != null) {
+ if (D) Log.d(TAG, "Send initial state");
+ handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
+ }
+ if (D) Log.d(TAG, "starting loop");
+ while (telemQueue != null) {
try {
state = read();
handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
}
}
- public TelemetryReader (AltosLink in_link, Handler in_handler) {
+ public TelemetryReader (AltosLink in_link, Handler in_handler, AltosFlightReader in_stacked) {
+ if (D) Log.d(TAG, "connected TelemetryReader create started");
link = in_link;
handler = in_handler;
+ stacked = in_stacked;
state = null;
telemQueue = new LinkedBlockingQueue<AltosLine>();
link.add_monitor(telemQueue);
+ link.set_telemetry(AltosLib.ao_telemetry_standard);
+
+ if (D) Log.d(TAG, "connected TelemetryReader created");
+ }
+
+ private static AltosFlightReader existing_data(AltosLink link) {
+ if (link == null)
+ return null;
+
+ File file = AltosPreferences.logfile(link.serial);
+ if (file != null) {
+ AltosStateIterable iterable = AltosStateIterable.iterable(file);
+ if (iterable != null)
+ return new AltosReplayReader(iterable.iterator(), file, false);
+ }
+ return null;
+ }
+
+ public TelemetryReader(AltosLink link, Handler handler) {
+ this(link, handler, existing_data(link));
}
}
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.content.Context;
import android.os.Bundle;
import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class TelemetryService extends Service implements LocationListener {
static final int MSG_TELEMETRY = 7;
static final int MSG_SETFREQUENCY = 8;
static final int MSG_CRC_ERROR = 9;
-
- public static final int STATE_NONE = 0;
- public static final int STATE_READY = 1;
- public static final int STATE_CONNECTING = 2;
- public static final int STATE_CONNECTED = 3;
+ static final int MSG_SETBAUD = 10;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
final Messenger mMessenger = new Messenger(mHandler); // Target we publish for clients to send messages to IncomingHandler.
// Name of the connected device
- private BluetoothDevice device = null;
+ String address;
private AltosBluetooth mAltosBluetooth = null;
- private AltosConfigData mConfigData = null;
private TelemetryReader mTelemetryReader = null;
private TelemetryLogger mTelemetryLogger = null;
+ // Local Bluetooth adapter
+ private BluetoothAdapter mBluetoothAdapter = null;
- // internally track state of bluetooth connection
- private int state = STATE_NONE;
+ private TelemetryState telemetry_state;
// Last data seen; send to UI when it starts
- private AltosState last_state;
- private Location last_location;
- private int last_crc_errors;
-
// Handler of incoming messages from clients.
static class IncomingHandler extends Handler {
private final WeakReference<TelemetryService> service;
@Override
public void handleMessage(Message msg) {
TelemetryService s = service.get();
+ if (s == null)
+ return;
switch (msg.what) {
case MSG_REGISTER_CLIENT:
s.mClients.add(msg.replyTo);
try {
// Now we try to send the freshly connected UI any relavant information about what
- // we're talking to - Basically state and Config Data.
- msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_STATE_CHANGE, s.state, -1, s.mConfigData));
- // We also send any recent telemetry or location data that's cached
- if (s.last_state != null) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_TELEMETRY, s.last_state ));
- if (s.last_location != null) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_LOCATION , s.last_location ));
- if (s.last_crc_errors != 0 ) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_CRC_ERROR, s.last_crc_errors));
+ // we're talking to
+ msg.replyTo.send(s.message());
} catch (RemoteException e) {
s.mClients.remove(msg.replyTo);
}
break;
case MSG_CONNECT:
if (D) Log.d(TAG, "Connect command received");
- s.device = (BluetoothDevice) msg.obj;
- s.startAltosBluetooth();
+ String address = (String) msg.obj;
+ AltosDroidPreferences.set_active_device(address);
+ s.startAltosBluetooth(address);
break;
case MSG_CONNECTED:
if (D) Log.d(TAG, "Connected to device");
- s.connected();
+ try {
+ s.connected();
+ } catch (InterruptedException ie) {
+ }
break;
case MSG_CONNECT_FAILED:
if (D) Log.d(TAG, "Connection failed... retrying");
- s.startAltosBluetooth();
+ if (s.address != null)
+ s.startAltosBluetooth(s.address);
break;
case MSG_DISCONNECTED:
- // Only do the following if we haven't been shutdown elsewhere..
- if (s.device != null) {
- if (D) Log.d(TAG, "Disconnected from " + s.device.getName());
- s.stopAltosBluetooth();
- }
+ Log.d(TAG, "MSG_DISCONNECTED");
+ s.stopAltosBluetooth();
break;
case MSG_TELEMETRY:
// forward telemetry messages
- s.last_state = (AltosState) msg.obj;
- s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_TELEMETRY, msg.obj));
+ s.telemetry_state.state = (AltosState) msg.obj;
+ if (D) Log.d(TAG, "MSG_TELEMETRY");
+ s.sendMessageToClients();
break;
case MSG_CRC_ERROR:
// forward crc error messages
- s.last_crc_errors = (Integer) msg.obj;
- s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_CRC_ERROR, msg.obj));
+ s.telemetry_state.crc_errors = (Integer) msg.obj;
+ if (D) Log.d(TAG, "MSG_CRC_ERROR");
+ s.sendMessageToClients();
break;
case MSG_SETFREQUENCY:
- if (s.state == STATE_CONNECTED) {
+ if (D) Log.d(TAG, "MSG_SETFREQUENCY");
+ s.telemetry_state.frequency = (Double) msg.obj;
+ if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {
try {
- s.mAltosBluetooth.set_radio_frequency((Double) msg.obj);
+ s.mAltosBluetooth.set_radio_frequency(s.telemetry_state.frequency);
+ s.mAltosBluetooth.save_frequency();
} catch (InterruptedException e) {
} catch (TimeoutException e) {
}
}
+ s.sendMessageToClients();
+ break;
+ case MSG_SETBAUD:
+ if (D) Log.d(TAG, "MSG_SETBAUD");
+ s.telemetry_state.telemetry_rate = (Integer) msg.obj;
+ if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {
+ s.mAltosBluetooth.set_telemetry_rate(s.telemetry_state.telemetry_rate);
+ s.mAltosBluetooth.save_telemetry_rate();
+ }
+ s.sendMessageToClients();
break;
default:
super.handleMessage(msg);
}
}
- private void sendMessageToClients(Message m) {
+ private Message message() {
+ if (telemetry_state == null)
+ Log.d(TAG, "telemetry_state null!");
+ return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state);
+ }
+
+ private void sendMessageToClients() {
+ Message m = message();
+ if (D) Log.d(TAG, String.format("Send message to %d clients", mClients.size()));
for (int i=mClients.size()-1; i>=0; i--) {
try {
+ if (D) Log.d(TAG, String.format("Send message to client %d", i));
mClients.get(i).send(m);
} catch (RemoteException e) {
mClients.remove(i);
private void stopAltosBluetooth() {
if (D) Log.d(TAG, "stopAltosBluetooth(): begin");
- setState(STATE_READY);
+ telemetry_state.connect = TelemetryState.CONNECT_READY;
if (mTelemetryReader != null) {
if (D) Log.d(TAG, "stopAltosBluetooth(): stopping TelemetryReader");
mTelemetryReader.interrupt();
mAltosBluetooth.close();
mAltosBluetooth = null;
}
- device = null;
- mConfigData = null;
+ telemetry_state.config = null;
+ if (D) Log.d(TAG, "stopAltosBluetooth(): send message to clients");
+ sendMessageToClients();
}
- private void startAltosBluetooth() {
- if (device == null) {
- return;
- }
+ private void startAltosBluetooth(String address) {
+ // Get the BLuetoothDevice object
+ BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
+
+ this.address = address;
if (mAltosBluetooth == null) {
if (D) Log.d(TAG, String.format("startAltosBluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress()));
mAltosBluetooth = new AltosBluetooth(device, mHandler);
- setState(STATE_CONNECTING);
+ telemetry_state.connect = TelemetryState.CONNECT_CONNECTING;
+ sendMessageToClients();
} else {
// This is a bit of a hack - if it appears we're still connected, we treat this as a restart.
// So, to give a suitable delay to teardown/bringup, we just schedule a resend of a message
// ... then we tear down the existing connection.
// We do it this way around so that we don't lose a reference to the device when this method
// is called on reception of MSG_CONNECT_FAILED in the handler above.
- mHandler.sendMessageDelayed(Message.obtain(null, MSG_CONNECT, device), 3000);
+ mHandler.sendMessageDelayed(Message.obtain(null, MSG_CONNECT, address), 3000);
stopAltosBluetooth();
}
}
- private synchronized void setState(int s) {
- if (D) Log.d(TAG, "setState(): " + state + " -> " + s);
- state = s;
-
- // This shouldn't be required - mConfigData should be null for any non-connected
- // state, but to be safe and to reduce message size
- AltosConfigData acd = (state == STATE_CONNECTED) ? mConfigData : null;
-
- sendMessageToClients(Message.obtain(null, AltosDroid.MSG_STATE_CHANGE, state, -1, acd));
- }
-
- private void connected() {
+ private void connected() throws InterruptedException {
+ if (D) Log.d(TAG, "connected top");
try {
if (mAltosBluetooth == null)
throw new InterruptedException("no bluetooth");
- mConfigData = mAltosBluetooth.config_data();
- } catch (InterruptedException e) {
+ telemetry_state.config = mAltosBluetooth.config_data();
+ mAltosBluetooth.set_radio_frequency(telemetry_state.frequency);
+ mAltosBluetooth.set_telemetry_rate(telemetry_state.telemetry_rate);
} catch (TimeoutException e) {
// If this timed out, then we really want to retry it, but
// probably safer to just retry the connection from scratch.
return;
}
- setState(STATE_CONNECTED);
+ if (D) Log.d(TAG, "connected bluetooth configured");
+ telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler);
mTelemetryReader.start();
-
+
+ if (D) Log.d(TAG, "connected TelemetryReader started");
+
mTelemetryLogger = new TelemetryLogger(this, mAltosBluetooth);
- }
+ if (D) Log.d(TAG, "Notify UI of connection");
+
+ sendMessageToClients();
+ }
private void onTimerTick() {
if (D) Log.d(TAG, "Timer wakeup");
try {
- if (mClients.size() <= 0 && state != STATE_CONNECTED) {
+ if (mClients.size() <= 0 && telemetry_state.connect != TelemetryState.CONNECT_CONNECTED) {
stopSelf();
}
} catch (Throwable t) {
@Override
public void onCreate() {
+ // 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();
+ }
+
+ // Initialise preferences
+ AltosDroidPreferences.init(this);
+
+ telemetry_state = new TelemetryState();
+
// Create a reference to the NotificationManager so that we can update our notifcation text later
//mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
- setState(STATE_READY);
+ telemetry_state.connect = TelemetryState.CONNECT_READY;
// Start our timer - first event in 10 seconds, then every 10 seconds after that.
timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 10000L, 10000L);
// Listen for GPS and Network position updates
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-
+
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
-// locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
+
+ String address = AltosDroidPreferences.active_device();
+ if (address != null)
+ startAltosBluetooth(address);
}
@Override
public void onLocationChanged(Location location) {
- last_location = location;
- sendMessageToClients(Message.obtain(null, AltosDroid.MSG_LOCATION, location));
+ telemetry_state.location = location;
+ if (D) Log.d(TAG, "location changed");
+ sendMessageToClients();
}
public void onStatusChanged(String provider, int status, Bundle extras) {
--- /dev/null
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import org.altusmetrum.altoslib_5.*;
+import android.location.Location;
+
+public class TelemetryState {
+ public static final int CONNECT_NONE = 0;
+ public static final int CONNECT_READY = 1;
+ public static final int CONNECT_CONNECTING = 2;
+ public static final int CONNECT_CONNECTED = 3;
+
+ int connect;
+ AltosConfigData config;
+ AltosState state;
+ Location location;
+ int crc_errors;
+ double frequency;
+ int telemetry_rate;
+
+ public TelemetryState() {
+ connect = CONNECT_NONE;
+ config = null;
+ state = null;
+ location = null;
+ crc_errors = 0;
+ frequency = AltosPreferences.frequency(0);
+ telemetry_rate = AltosPreferences.telemetry_rate(0);
+ }
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosAccel extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosCRCException extends Exception {
public int rssi;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
LinkedList<AltosState> pad_states;
AltosState state;
+ static boolean has_basic;
+ static boolean has_battery;
+ static boolean has_flight_state;
+ static boolean has_advanced;
+ static boolean has_gps;
+ static boolean has_gps_sat;
+ static boolean has_companion;
+
static final int ALTOS_CSV_VERSION = 5;
/* Version 4 format:
* accelerometer speed (m/s)
* barometer speed (m/s)
* temp (°C)
- * battery (V)
* drogue (V)
* main (V)
*
+ * Battery
+ * battery (V)
+ *
* Advanced sensors (if available)
* accel_x (m/s²)
* accel_y (m/s²)
* from_pad_azimuth (deg true)
* from_pad_range (m)
* from_pad_elevation (deg from horizon)
+ * pdop
* hdop
+ * vdop
*
* GPS Sat data
* C/N0 data for all 32 valid SDIDs
void write_general(AltosState state) {
out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d",
ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign,
- (double) state.time, (double) state.tick / 100.0,
+ (double) state.time_since_boost(), (double) state.tick / 100.0,
state.rssi,
state.status & 0x7f);
}
}
void write_basic_header() {
- out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,battery_voltage,drogue_voltage,main_voltage");
+ out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");
}
void write_basic(AltosState state) {
- out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f",
+ out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f",
state.acceleration(),
state.pressure(),
state.altitude(),
state.speed(),
state.speed(),
state.temperature,
- state.battery_voltage,
state.apogee_voltage,
state.main_voltage);
}
+ void write_battery_header() {
+ out.printf("battery_voltage");
+ }
+
+ void write_battery(AltosState state) {
+ out.printf("%5.2f", state.battery_voltage);
+ }
+
void write_advanced_header() {
out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z");
}
imu = new AltosIMU();
if (mag == null)
mag = new AltosMag();
- out.printf("%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d",
+ out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
imu.accel_x, imu.accel_y, imu.accel_z,
imu.gyro_x, imu.gyro_y, imu.gyro_z,
mag.x, mag.y, mag.z);
}
void write_gps_header() {
- out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,hdop");
+ out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,pdop,hdop,vdop");
}
void write_gps(AltosState state) {
if (from_pad == null)
from_pad = new AltosGreatCircle();
- out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%8.1f,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f",
+ out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%8.1f,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f,%6.1f,%6.1f",
gps.connected?1:0,
gps.locked?1:0,
gps.nsat,
state.range,
from_pad.bearing,
state.elevation,
- gps.hdop);
+ gps.pdop,
+ gps.hdop,
+ gps.vdop);
}
void write_gps_sat_header() {
out.printf(",0");
}
- void write_header(boolean advanced, boolean gps, boolean companion) {
+ void write_header() {
out.printf("#"); write_general_header();
- out.printf(","); write_flight_header();
- out.printf(","); write_basic_header();
- if (advanced)
- out.printf(","); write_advanced_header();
- if (gps) {
- out.printf(","); write_gps_header();
- out.printf(","); write_gps_sat_header();
+ if (has_flight_state) {
+ out.printf(",");
+ write_flight_header();
}
- if (companion) {
- out.printf(","); write_companion_header();
+ if (has_basic) {
+ out.printf(",");
+ write_basic_header();
+ }
+ if (has_battery) {
+ out.printf(",");
+ write_battery_header();
+ }
+ if (has_advanced) {
+ out.printf(",");
+ write_advanced_header();
+ }
+ if (has_gps) {
+ out.printf(",");
+ write_gps_header();
+ }
+ if (has_gps_sat) {
+ out.printf(",");
+ write_gps_sat_header();
+ }
+ if (has_companion) {
+ out.printf(",");
+ write_companion_header();
}
out.printf ("\n");
}
void write_one(AltosState state) {
- write_general(state); out.printf(",");
- write_flight(state); out.printf(",");
- write_basic(state); out.printf(",");
- if (state.imu != null || state.mag != null)
+ write_general(state);
+ if (has_flight_state) {
+ out.printf(",");
+ write_flight(state);
+ }
+ if (has_basic) {
+ out.printf(",");
+ write_basic(state);
+ }
+ if (has_battery) {
+ out.printf(",");
+ write_battery(state);
+ }
+ if (has_advanced) {
+ out.printf(",");
write_advanced(state);
- if (state.gps != null) {
+ }
+ if (has_gps) {
+ out.printf(",");
+ write_gps(state);
+ }
+ if (has_gps_sat) {
out.printf(",");
- write_gps(state); out.printf(",");
write_gps_sat(state);
}
- if (state.companion != null) {
+ if (has_companion) {
out.printf(",");
write_companion(state);
}
out.printf ("\n");
}
- void flush_pad() {
+ private void flush_pad() {
while (!pad_states.isEmpty()) {
write_one (pad_states.remove());
}
}
- public void write(AltosState state) {
+ private void write(AltosState state) {
if (state.state == AltosLib.ao_flight_startup)
return;
if (!header_written) {
- write_header(state.imu != null || state.mag != null,
- state.gps != null, state.companion != null);
+ write_header();
header_written = true;
}
if (!seen_boost) {
pad_states.add(state);
}
- public PrintStream out() {
+ private PrintStream out() {
return out;
}
public void write(AltosStateIterable states) {
states.write_comments(out());
+
+ has_flight_state = false;
+ has_basic = false;
+ has_battery = false;
+ has_advanced = false;
+ has_gps = false;
+ has_gps_sat = false;
+ has_companion = false;
+ for (AltosState state : states) {
+ if (state.state != AltosLib.ao_flight_stateless && state.state != AltosLib.ao_flight_invalid && state.state != AltosLib.ao_flight_startup)
+ has_flight_state = true;
+ if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING)
+ has_basic = true;
+ if (state.battery_voltage != AltosLib.MISSING)
+ has_battery = true;
+ if (state.imu != null || state.mag != null)
+ has_advanced = true;
+ if (state.gps != null) {
+ has_gps = true;
+ if (state.gps.cc_gps_sat != null)
+ has_gps_sat = true;
+ }
+ if (state.companion != null)
+ has_companion = true;
+ }
for (AltosState state : states)
write(state);
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosCompanion {
public final static int board_id_telescience = 0x0a;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.*;
import java.text.*;
public int log_format;
public int log_space;
public String version;
+ public int altitude_32;
/* Strings returned */
public LinkedList<String> lines;
public String callsign;
public int radio_enable;
public int radio_calibration;
+ public int telemetry_rate;
/* Old HAS_RADIO values */
public int radio_channel;
public int radio_setting;
/* HAS_LOG */
public int flight_log_max;
+ public int log_fixed;
/* HAS_IGNITE */
public int ignite_mode;
/* HAS_APRS */
public int aprs_interval;
+ public int aprs_ssid;
/* HAS_BEEP */
public int beep;
radio_calibration = -1;
radio_channel = -1;
radio_setting = -1;
+ telemetry_rate = -1;
accel_cal_plus = -1;
accel_cal_minus = -1;
pad_orientation = -1;
flight_log_max = -1;
+ log_fixed = -1;
ignite_mode = -1;
aes_key = "";
pyro_firing_time = -1;
aprs_interval = -1;
+ aprs_ssid = -1;
beep = -1;
try { flight = get_int(line, "current-flight"); } catch (Exception e) {}
try { log_format = get_int(line, "log-format"); } catch (Exception e) {}
try { log_space = get_int(line, "log-space"); } catch (Exception e) {}
+ try { altitude_32 = get_int(line, "altitude-32"); } catch (Exception e) {}
try { version = get_string(line, "software-version"); } catch (Exception e) {}
/* Version also contains MS5607 info, which we ignore here */
try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {}
try { radio_enable = get_int(line, "Radio enable:"); } catch (Exception e) {}
try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {}
+ try { telemetry_rate = get_int(line, "Telemetry rate:"); } catch (Exception e) {}
/* Old HAS_RADIO values */
try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {}
/* HAS_LOG */
try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {}
+ try { log_fixed = get_int(line, "Log fixed:"); } catch (Exception e) {}
/* HAS_IGNITE */
try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {}
/* HAS_APRS */
try { aprs_interval = get_int(line, "APRS interval:"); } catch (Exception e) {}
+ try { aprs_ssid = get_int(line, "APRS SSID:"); } catch (Exception e) {}
/* HAS_BEEP */
try { beep = get_int(line, "Beeper setting:"); } catch (Exception e) {}
return radio_frequency >= 0 || radio_setting >= 0 || radio_channel >= 0;
}
+ public boolean has_telemetry_rate() {
+ return telemetry_rate >= 0;
+ }
+
public void set_frequency(double freq) {
int frequency = radio_frequency;
int setting = radio_setting;
return false;
if (product.startsWith("TeleMetrum-v2"))
return false;
+ if (product.startsWith("EasyMega"))
+ return false;
return true;
}
callsign = source.callsign();
if (radio_calibration >= 0)
radio_calibration = source.radio_calibration();
+ if (telemetry_rate >= 0)
+ telemetry_rate = source.telemetry_rate();
/* HAS_ACCEL */
if (pad_orientation >= 0)
/* HAS_APRS */
if (aprs_interval >= 0)
aprs_interval = source.aprs_interval();
+ if (aprs_ssid >= 0)
+ aprs_ssid = source.aprs_ssid();
/* HAS_BEEP */
if (beep >= 0)
dest.set_serial(serial);
dest.set_product(product);
dest.set_version(version);
+ dest.set_altitude_32(altitude_32);
dest.set_main_deploy(main_deploy);
dest.set_apogee_delay(apogee_delay);
dest.set_apogee_lockout(apogee_lockout);
dest.set_radio_calibration(radio_calibration);
dest.set_radio_frequency(frequency());
+ dest.set_telemetry_rate(telemetry_rate);
boolean max_enabled = true;
if (log_space() == 0)
max_enabled = false;
+ if (log_fixed > 0)
+ max_enabled = false;
+
switch (log_format) {
case AltosLib.AO_LOG_FORMAT_TINY:
max_enabled = false;
dest.set_pyros(null);
dest.set_pyro_firing_time(pyro_firing_time);
dest.set_aprs_interval(aprs_interval);
+ dest.set_aprs_ssid(aprs_ssid);
dest.set_beep(beep);
dest.set_tracker_motion(tracker_motion);
dest.set_tracker_interval(tracker_interval);
radio_calibration);
/* When remote, reset the dongle frequency at the same time */
if (remote) {
+ link.flush_output();
link.stop_remote();
link.set_radio_frequency(frequency);
+ link.flush_output();
link.start_remote();
}
}
- if (callsign != null)
+ if (telemetry_rate >= 0) {
+ link.printf("c T %d\n", telemetry_rate);
+ if (remote) {
+ link.flush_output();
+ link.stop_remote();
+ link.set_telemetry_rate(telemetry_rate);
+ link.flush_output();
+ link.start_remote();
+ }
+ }
+
+ if (callsign != null) {
link.printf("c c %s\n", callsign);
+ if (remote) {
+ link.flush_output();
+ link.stop_remote();
+ link.set_callsign(callsign);
+ link.flush_output();
+ link.start_remote();
+ }
+ }
+
if (radio_enable >= 0)
link.printf("c e %d\n", radio_enable);
/* HAS_APRS */
if (aprs_interval >= 0)
link.printf("c A %d\n", aprs_interval);
+ if (aprs_ssid >= 0)
+ link.printf("c S %d\n", aprs_ssid);
/* HAS_BEEP */
if (beep >= 0)
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosConfigDataException extends Exception {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public interface AltosConfigValues {
/* set and get all of the dialog values */
public abstract void set_serial(int serial);
+ public abstract void set_altitude_32(int altitude_32);
+
public abstract void set_main_deploy(int new_main_deploy);
public abstract int main_deploy() throws AltosConfigDataException;
public abstract String callsign();
+ public abstract void set_telemetry_rate(int new_telemetry_rate);
+
+ public abstract int telemetry_rate() throws AltosConfigDataException;
+
public abstract void set_flight_log_max(int new_flight_log_max);
public abstract void set_flight_log_max_enabled(boolean enable);
public abstract void set_aprs_interval(int new_aprs_interval);
+ public abstract int aprs_ssid() throws AltosConfigDataException;
+
+ public abstract void set_aprs_ssid(int new_aprs_ssid);
+
public abstract int beep() throws AltosConfigDataException;
public abstract void set_beep(int new_beep);
/*
* Sensor data conversion functions
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosConvert {
/*
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
public static final byte GET_CHIP_ID = 0x68;
- AltosLink link;
+ private AltosLink link;
boolean debug_mode;
int i = 0;
int start = 0;
while (i < length) {
- String line = link.get_reply().trim();
+ String line = link.get_reply();
+ if (line == null)
+ throw new IOException("No reply");
+
+ line = line.trim();
if (!AltosLib.ishex(line) || line.length() % 2 != 0)
throw new IOException(
String.format
public AltosDebug (AltosLink link) {
this.link = link;
}
-}
\ No newline at end of file
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosDistance extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
/* AO_LOG_GPS_TIME elements */
public int latitude() { return data32(0); }
public int longitude() { return data32(4); }
- public int altitude() { return data16(8); }
+ public int altitude_low() { return data16(8); }
public int hour() { return data8(10); }
public int minute() { return data8(11); }
public int second() { return data8(12); }
public int hdop() { return data8(23); }
public int vdop() { return data8(24); }
public int mode() { return data8(25); }
+ public int altitude_high() { return data16(26); }
public boolean has_seconds() { return cmd == AltosLib.AO_LOG_GPS_TIME; }
switch (cmd) {
case AltosLib.AO_LOG_FLIGHT:
- state.set_boost_tick(tick);
- state.set_flight(flight());
+ if (state.flight == AltosLib.MISSING) {
+ state.set_boost_tick(tick);
+ state.set_flight(flight());
+ }
/* no place to log start lat/lon yet */
break;
case AltosLib.AO_LOG_GPS_TIME:
gps = state.make_temp_gps(false);
gps.lat = latitude() / 1e7;
gps.lon = longitude() / 1e7;
- gps.alt = altitude();
+ if (state.altitude_32())
+ gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
+ else
+ gps.alt = altitude_low();
gps.hour = hour();
gps.minute = minute();
gps.ground_speed = ground_speed() * 1.0e-2;
gps.course = course() * 2;
gps.climb_rate = climb_rate() * 1.0e-2;
- gps.hdop = hdop();
- gps.vdop = vdop();
+ if (state.compare_version("1.4.9") >= 0) {
+ gps.pdop = pdop() / 10.0;
+ gps.hdop = hdop() / 10.0;
+ gps.vdop = vdop() / 10.0;
+ } else {
+ gps.pdop = pdop() / 100.0;
+ if (gps.pdop < 0.8)
+ gps.pdop += 2.56;
+ gps.hdop = hdop() / 100.0;
+ if (gps.hdop < 0.8)
+ gps.hdop += 2.56;
+ gps.vdop = vdop() / 100.0;
+ if (gps.vdop < 0.8)
+ gps.vdop += 2.56;
+ }
break;
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
case AltosLib.AO_LOG_SOFTWARE_VERSION:
state.set_firmware_version(data);
break;
+ case AltosLib.AO_LOG_FREQUENCY:
+ case AltosLib.AO_LOG_APOGEE_LOCKOUT:
+ case AltosLib.AO_LOG_RADIO_RATE:
+ case AltosLib.AO_LOG_IGNITE_MODE:
+ case AltosLib.AO_LOG_PAD_ORIENTATION:
+ case AltosLib.AO_LOG_RADIO_ENABLE:
+ case AltosLib.AO_LOG_AES_KEY:
+ case AltosLib.AO_LOG_APRS:
+ case AltosLib.AO_LOG_BEEP_SETTING:
+ case AltosLib.AO_LOG_TRACKER_SETTING:
+ case AltosLib.AO_LOG_PYRO_TIME:
+ case AltosLib.AO_LOG_APRS_ID:
+ break;
+ case AltosLib.AO_LOG_ALTITUDE_32:
+ state.set_altitude_32(config_a);
+ break;
}
}
case AltosLib.AO_LOG_BARO_CRC:
out.printf ("# Baro crc: %d\n", config_a);
break;
+ case AltosLib.AO_LOG_FREQUENCY:
+ case AltosLib.AO_LOG_APOGEE_LOCKOUT:
+ case AltosLib.AO_LOG_RADIO_RATE:
+ case AltosLib.AO_LOG_IGNITE_MODE:
+ case AltosLib.AO_LOG_PAD_ORIENTATION:
+ case AltosLib.AO_LOG_RADIO_ENABLE:
+ case AltosLib.AO_LOG_AES_KEY:
+ case AltosLib.AO_LOG_APRS:
+ case AltosLib.AO_LOG_BEEP_SETTING:
+ case AltosLib.AO_LOG_TRACKER_SETTING:
+ case AltosLib.AO_LOG_PYRO_TIME:
+ case AltosLib.AO_LOG_APRS_ID:
+ break;
+ case AltosLib.AO_LOG_ALTITUDE_32:
+ out.printf("# Altitude-32: %d\n", config_a);
+ break;
}
}
} else if (tokens[0].equals("log-format")) {
cmd = AltosLib.AO_LOG_LOG_FORMAT;
config_a = Integer.parseInt(tokens[1]);
+ } else if (tokens[0].equals("altitude-32")) {
+ cmd = AltosLib.AO_LOG_ALTITUDE_32;
+ config_a = Integer.parseInt(tokens[1]);
} else if (tokens[0].equals("software-version")) {
cmd = AltosLib.AO_LOG_SOFTWARE_VERSION;
data = tokens[1];
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
/* AO_LOG_GPS_TIME elements */
public int latitude() { return data32(0); }
public int longitude() { return data32(4); }
- public int altitude() { return data16(8); }
+ public int altitude_low() { return data16(8); }
public int hour() { return data8(10); }
public int minute() { return data8(11); }
public int second() { return data8(12); }
public int hdop() { return data8(23); }
public int vdop() { return data8(24); }
public int mode() { return data8(25); }
+ public int altitude_high() { return data16(26); }
/* AO_LOG_GPS_SAT elements */
public int nsat() { return data16(0); }
gps = state.make_temp_gps(false);
gps.lat = latitude() / 1e7;
gps.lon = longitude() / 1e7;
- gps.alt = altitude();
+
+ if (state.altitude_32())
+ gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
+ else
+ gps.alt = altitude_low();
gps.hour = hour();
gps.minute = minute();
gps.ground_speed = ground_speed() * 1.0e-2;
gps.course = course() * 2;
gps.climb_rate = climb_rate() * 1.0e-2;
- gps.hdop = hdop();
- gps.vdop = vdop();
+ if (state.compare_version("1.4.9") >= 0) {
+ gps.pdop = pdop() / 10.0;
+ gps.hdop = hdop() / 10.0;
+ gps.vdop = vdop() / 10.0;
+ } else {
+ gps.pdop = pdop() / 100.0;
+ if (gps.pdop < 0.8)
+ gps.pdop += 2.56;
+ gps.hdop = hdop() / 100.0;
+ if (gps.hdop < 0.8)
+ gps.hdop += 2.56;
+ gps.vdop = vdop() / 100.0;
+ if (gps.vdop < 0.8)
+ gps.vdop += 2.56;
+ }
break;
case AltosLib.AO_LOG_GPS_SAT:
state.set_tick(tick);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
/* AO_LOG_GPS_POS elements */
public int latitude() { return data32(0); }
public int longitude() { return data32(4); }
- public int altitude() { return data16(8); }
+ public int altitude_low() { return data16(8); }
+ public int altitude_high() { return data16(10); }
/* AO_LOG_GPS_TIME elements */
public int hour() { return data8(0); }
public int year() { return data8(4); }
public int month() { return data8(5); }
public int day() { return data8(6); }
+ public int pdop() { return data8(7); }
/* AO_LOG_GPS_SAT elements */
public int nsat() { return data8(0); }
gps = state.make_temp_gps(false);
gps.lat = latitude() / 1e7;
gps.lon = longitude() / 1e7;
- gps.alt = altitude();
+ if (state.altitude_32())
+ gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
+ else
+ gps.alt = altitude_low();
break;
case AltosLib.AO_LOG_GPS_TIME:
gps = state.make_temp_gps(false);
gps.year = 2000 + year();
gps.month = month();
gps.day = day();
+ gps.pdop = pdop() / 10.0;
break;
case AltosLib.AO_LOG_GPS_SAT:
gps = state.make_temp_gps(true);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public interface AltosEepromMonitor {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.File;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
debug = new AltosDebug(link);
input = new FileInputStream(file);
image = new AltosHexfile(input);
- if (debug != null && !debug.check_connection()) {
+
+ boolean connection_ok = true;
+
+ if (debug != null) {
+ try {
+ connection_ok = debug.check_connection();
+ } catch (IOException ie) {
+ debug.close();
+ throw ie;
+ } catch (InterruptedException ie) {
+ debug.close();
+ throw ie;
+ }
+ }
+ if (!connection_ok) {
debug.close();
throw new IOException("Debug port not connected");
}
}
-}
\ No newline at end of file
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public interface AltosFlashListener {
public void position(String label, int percent);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
import java.io.*;
import java.util.concurrent.*;
-public class AltosFlightReader {
+public abstract class AltosFlightReader {
public String name;
public int serial;
- public void init() { }
+ public void init() {}
- public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
+ public abstract AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException;
- public void close(boolean interrupted) { }
+ public abstract void close(boolean interrupted);
public void set_frequency(double frequency) throws InterruptedException, TimeoutException { }
public void set_telemetry(int telemetry) { }
+ public void set_telemetry_rate(int telemetry_rate) throws InterruptedException, TimeoutException { }
+
public void save_telemetry() { }
+ public void save_telemetry_rate() { }
+
public void update(AltosState state) throws InterruptedException { }
public boolean supports_telemetry(int telemetry) { return false; }
+ public boolean supports_telemetry_rate(int telemetry_rate) { return false; }
+
public File backing_file() { return null; }
public boolean has_monitor_battery() throws InterruptedException { return false; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosFrequency {
public double frequency;
frequency = f;
description = d;
}
-}
\ No newline at end of file
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
import java.util.concurrent.*;
public double ground_speed; /* m/s */
public int course; /* degrees */
public double climb_rate; /* m/s */
+ public double pdop; /* unitless */
public double hdop; /* unitless */
public double vdop; /* unitless */
- public int h_error; /* m */
- public int v_error; /* m */
+ public double h_error; /* m */
+ public double v_error; /* m */
public AltosGPSSat[] cc_gps_sat; /* tracking data */
AltosLib.MISSING, 1/100.0);
course = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_COURSE,
AltosLib.MISSING);
+ pdop = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_PDOP, MISSING, 1.0);
hdop = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_HDOP, MISSING, 1.0);
vdop = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_VDOP, MISSING, 1.0);
h_error = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_HERROR, MISSING);
cc_gps_sat[cc_gps_sat.length - 1] = sat;
}
- public AltosGPS() {
+ private void init() {
lat = AltosLib.MISSING;
lon = AltosLib.MISSING;
alt = AltosLib.MISSING;
+ ground_speed = AltosLib.MISSING;
+ course = AltosLib.MISSING;
+ climb_rate = AltosLib.MISSING;
+ pdop = AltosLib.MISSING;
+ hdop = AltosLib.MISSING;
+ vdop = AltosLib.MISSING;
+ h_error = AltosLib.MISSING;
+ v_error = AltosLib.MISSING;
ClearGPSTime();
cc_gps_sat = null;
}
+ public AltosGPS() {
+ init();
+ }
+
public AltosGPS clone() {
AltosGPS g = new AltosGPS();
g.ground_speed = ground_speed; /* m/s */
g.course = course; /* degrees */
g.climb_rate = climb_rate; /* m/s */
- g.hdop = hdop; /* unitless? */
+ g.pdop = pdop; /* unitless */
+ g.hdop = hdop; /* unitless */
+ g.vdop = vdop; /* unitless */
g.h_error = h_error; /* m */
g.v_error = v_error; /* m */
ground_speed = old.ground_speed; /* m/s */
course = old.course; /* degrees */
climb_rate = old.climb_rate; /* m/s */
+ pdop = old.pdop; /* unitless? */
hdop = old.hdop; /* unitless? */
- h_error = old.h_error; /* m */
- v_error = old.v_error; /* m */
+ vdop = old.vdop; /* unitless? */
+ h_error = old.h_error; /* m */
+ v_error = old.v_error; /* m */
if (old.cc_gps_sat != null) {
cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length];
}
}
} else {
- lat = AltosLib.MISSING;
- lon = AltosLib.MISSING;
- alt = AltosLib.MISSING;
- ClearGPSTime();
- cc_gps_sat = null;
+ init();
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosGPSSat {
public int svid;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosHeight extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.LinkedList;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosHexsym {
String name;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
AltosIdler.idle_ms5607, AltosIdler.idle_mma655x,
AltosIdler.idle_imu, AltosIdler.idle_mag,
AltosIdler.idle_sensor_mega),
+ new AltosIdler("EasyMega",
+ AltosIdler.idle_ms5607, AltosIdler.idle_mma655x,
+ AltosIdler.idle_imu, AltosIdler.idle_mag,
+ AltosIdler.idle_sensor_mega),
};
AltosLink link;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public interface AltosIdleMonitorListener {
public void update(AltosState state, AltosListenerState listener_state);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
double gps_start_altitude;
static final String[] kml_state_colors = {
- "FF000000",
- "FF000000",
- "FF000000",
- "FF0000FF",
- "FF4080FF",
- "FF00FFFF",
- "FFFF0000",
- "FF00FF00",
- "FF000000",
- "FFFFFFFF"
+ "FF000000", // startup
+ "FF000000", // idle
+ "FF000000", // pad
+ "FF0000FF", // boost
+ "FF4080FF", // fast
+ "FF00FFFF", // coast
+ "FFFF0000", // drogue
+ "FF00FF00", // main
+ "FF000000", // landed
+ "FFFFFFFF", // invalid
+ "FFFF0000", // stateless
};
+ static String state_color(int state) {
+ if (state < 0 || kml_state_colors.length <= state)
+ return kml_state_colors[AltosLib.ao_flight_invalid];
+ return kml_state_colors[state];
+ }
+
static final String kml_header_start =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n" +
void state_start(AltosState state) {
String state_name = AltosLib.state_name(state.state);
- out.printf(kml_style_start, state_name, kml_state_colors[state.state]);
+ String state_color = state_color(state.state);
+ out.printf(kml_style_start, state_name, state_color);
out.printf("\tState: %s\n", state_name);
out.printf("%s", kml_style_end);
out.printf(kml_placemark_start, state_name, state_name);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosLatitude extends AltosLocation {
public String pos() { return "N"; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.*;
import java.io.*;
public static final int AO_LOG_SERIAL_NUMBER = 2002;
public static final int AO_LOG_LOG_FORMAT = 2003;
+ public static final int AO_LOG_FREQUENCY = 2004;
+ public static final int AO_LOG_APOGEE_LOCKOUT = 2005;
+ public static final int AO_LOG_RADIO_RATE = 2006;
+ public static final int AO_LOG_IGNITE_MODE = 2007;
+ public static final int AO_LOG_PAD_ORIENTATION = 2008;
+ public static final int AO_LOG_RADIO_ENABLE = 2009;
+ public static final int AO_LOG_AES_KEY = 2010;
+ public static final int AO_LOG_APRS = 2011;
+ public static final int AO_LOG_BEEP_SETTING = 2012;
+ public static final int AO_LOG_TRACKER_SETTING = 2013;
+ public static final int AO_LOG_PYRO_TIME = 2014;
+ public static final int AO_LOG_APRS_ID = 2015;
+ public static final int AO_LOG_ALTITUDE_32 = 2016;
+
/* Added for header fields in telemega files */
public static final int AO_LOG_BARO_RESERVED = 3000;
public static final int AO_LOG_BARO_SENS = 3001;
public final static int product_telegps = 0x0025;
public final static int product_easymini = 0x0026;
public final static int product_telemini = 0x0027;
+ public final static int product_easymega = 0x0028;
public final static int product_altusmetrum_min = 0x000a;
public final static int product_altusmetrum_max = 0x002c;
new Product("megadongle", product_megadongle),
new Product("telegps", product_telegps),
new Product("easymini", product_easymini),
- new Product("telemini", product_telemini)
+ new Product("telemini", product_telemini),
+ new Product("easymega", product_easymega)
};
public static int name_to_product(String name) {
"Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8"
};
+ public static final int ao_telemetry_rate_38400 = 0;
+ public static final int ao_telemetry_rate_9600 = 1;
+ public static final int ao_telemetry_rate_2400 = 2;
+ public static final int ao_telemetry_rate_max = 2;
+
+ public static final Integer[] ao_telemetry_rate_values = {
+ 38400, 9600, 2400
+ };
+
public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt";
public static final int ao_telemetry_standard_len = 32;
telemetry));
}
+ private static int[] split_version(String version) {
+ String[] tokens = version.split("\\.");
+ int[] ret = new int[tokens.length];
+ for (int i = 0; i < tokens.length; i++)
+ ret[i] = Integer.parseInt(tokens[i]);
+ return ret;
+ }
+
+ public static int compare_version(String version_a, String version_b) {
+ int[] a = split_version(version_a);
+ int[] b = split_version(version_b);
+
+ for (int i = 0; i < Math.min(a.length, b.length); i++) {
+ if (a[i] < b[i])
+ return -1;
+ if (a[i] > b[i])
+ return 1;
+ }
+ if (a.length < b.length)
+ return -1;
+ if (a.length > b.length)
+ return 1;
+ return 0;
+ }
+
private static String[] state_to_string = {
"startup",
"idle",
return false;
}
- public static boolean ishex(int c) {
+ public static final boolean ishex(int c) {
if ('0' <= c && c <= '9')
return true;
if ('a' <= c && c <= 'f')
return false;
}
- public static boolean ishex(String s) {
+ public static final boolean ishex(String s) {
for (int i = 0; i < s.length(); i++)
if (!ishex(s.charAt(i)))
return false;
if ((s.length() & 1) != 0)
throw new NumberFormatException(String.format("invalid line \"%s\"", s));
- n = s.length() / 2;
+ byte[] bytes = s.getBytes(unicode_set);
+ n = bytes.length / 2;
r = new int[n];
- for (i = 0; i < n; i++)
- r[i] = hexbyte(s, i * 2);
+ for (i = 0; i < n; i++) {
+ int h = fromhex(bytes[(i << 1)]);
+ int l = fromhex(bytes[(i << 1) + 1]);
+ if (h < 0 || l < 0)
+ throw new NumberFormatException(String.format("invalid hex \"%c%c\"",
+ bytes[(i<<1)], bytes[(i<<1) + 1]));
+ r[i] = (h << 4) + l;
+ }
return r;
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosLine {
public String line;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.concurrent.*;
if (!can_cancel && remote)
System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
- if (remote && can_cancel)
+ if (remote && can_cancel) {
timeout = 500;
+ switch (telemetry_rate) {
+ case AltosLib.ao_telemetry_rate_38400:
+ default:
+ timeout = 500;
+ break;
+ case AltosLib.ao_telemetry_rate_9600:
+ timeout = 2000;
+ break;
+ case AltosLib.ao_telemetry_rate_2400:
+ timeout = 8000;
+ break;
+ }
+ }
try {
++in_reply;
}
public void flush_output() {
+ if (pending_output == null)
+ return;
for (String s : pending_output)
System.out.print(s);
pending_output.clear();
*/
public boolean monitor_mode = false;
public int telemetry = AltosLib.ao_telemetry_standard;
+ public int telemetry_rate = -1;
public double frequency;
public String callsign;
AltosConfigData config_data;
flush_output();
}
+ public void set_telemetry_rate(int in_telemetry_rate) {
+ telemetry_rate = in_telemetry_rate;
+ if (monitor_mode)
+ printf("m 0\nc T %d\nm %x\n", telemetry_rate, telemetry_len());
+ else
+ printf("c T %d\n", telemetry_rate);
+ flush_output();
+ }
+
public void set_monitor(boolean monitor) {
monitor_mode = monitor;
if (monitor)
flush_output();
}
- public AltosConfigData config_data() throws InterruptedException, TimeoutException {
+ public AltosConfigData config_data() throws InterruptedException, TimeoutException {
synchronized(config_data_lock) {
- if (config_data == null)
+ if (config_data == null) {
+ printf("m 0\n");
config_data = new AltosConfigData(this);
+ if (monitor_mode)
+ set_monitor(true);
+ }
return config_data;
}
}
if (debug)
System.out.printf("start remote %7.3f\n", frequency);
set_radio_frequency(frequency);
- set_callsign(AltosPreferences.callsign());
+ if (telemetry_rate < 0)
+ telemetry_rate = AltosPreferences.telemetry_rate(serial);
+ set_telemetry_rate(telemetry_rate);
+ if (callsign.equals(""))
+ callsign = AltosPreferences.callsign();
+ set_callsign(callsign);
printf("p\nE 0\n");
flush_input();
remote = true;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosListenerState {
public int crc_errors;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public abstract class AltosLocation extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.text.*;
}
log_file.flush();
file = a;
+ AltosPreferences.set_logfile(link.serial, file);
}
return log_file != null;
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosLongitude extends AltosLocation {
public String pos() { return "E"; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.*;
int accel;
- public boolean parse_line(String line) {
- String[] items = line.split("\\s+");
- if (line.startsWith("MMA655X value:")) {
- if (items.length >= 3)
- accel = Integer.parseInt(items[1]);
- } else
- return false;
- return true;
+ public boolean parse_line(String line) throws NumberFormatException {
+ if (line.startsWith("MMA655X value")) {
+ String[] items = line.split("\\s+");
+ if (items.length >= 3) {
+ accel = Integer.parseInt(items[2]);
+ return true;
+ }
+ }
+ return false;
}
public AltosMma655x() {
if (mma655x != null)
state.set_accel(mma655x.accel);
} catch (TimeoutException te) {
+ } catch (NumberFormatException ne) {
}
}
- public AltosMma655x(AltosLink link) throws InterruptedException, TimeoutException {
+ public AltosMma655x(AltosLink link) throws InterruptedException, TimeoutException, NumberFormatException {
this();
link.printf("A\n");
for (;;) {
String line = link.get_reply_no_dialog(5000);
if (line == null)
throw new TimeoutException();
- if (!parse_line(line))
+ if (parse_line(line))
break;
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosNoSymbol extends Exception {
public AltosNoSymbol(String name) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosOrient extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
/* telemetry format preference name */
public final static String telemetryPreferenceFormat = "TELEMETRY-%d";
+ /* telemetry rate format preference name */
+ public final static String telemetryRatePreferenceFormat = "RATE-%d";
+
+ /* log file format preference name */
+ public final static String logfilePreferenceFormat = "LOGFILE-%d";
+
/* voice preference name */
public final static String voicePreference = "VOICE";
/* scanning telemetry preferences name */
public final static String scanningTelemetryPreference = "SCANNING-TELEMETRY";
+ /* scanning telemetry rate preferences name */
+ public final static String scanningTelemetryRatePreference = "SCANNING-RATE";
+
/* Launcher serial preference name */
public final static String launcherSerialPreference = "LAUNCHER-SERIAL";
/* Telemetry (map serial to telemetry format) */
public static Hashtable<Integer, Integer> telemetries;
+ /* Telemetry rate (map serial to telemetry format) */
+ public static Hashtable<Integer, Integer> telemetry_rates;
+
+ /* Log file (map serial to logfile name) */
+ public static Hashtable<Integer, File> logfiles;
+
/* Voice preference */
public static boolean voice;
/* Scanning telemetry */
public static int scanning_telemetry;
+ public static int scanning_telemetry_rate;
+
/* List of frequencies */
public final static String common_frequencies_node_name = "COMMON-FREQUENCIES";
public static AltosFrequency[] common_frequencies;
public static int launcher_channel;
public static void init(AltosPreferencesBackend in_backend) {
+
+ if (backend != null)
+ return;
+
backend = in_backend;
/* Initialize logdir from preferences */
telemetries = new Hashtable<Integer,Integer>();
+ telemetry_rates = new Hashtable<Integer,Integer>();
+
+ logfiles = new Hashtable<Integer,File>();
+
voice = backend.getBoolean(voicePreference, true);
callsign = backend.getString(callsignPreference,"N0CALL");
scanning_telemetry = backend.getInt(scanningTelemetryPreference,(1 << AltosLib.ao_telemetry_standard));
+ scanning_telemetry_rate = backend.getInt(scanningTelemetryRatePreference,(1 << AltosLib.ao_telemetry_rate_38400));
+
launcher_serial = backend.getInt(launcherSerialPreference, 0);
launcher_channel = backend.getInt(launcherChannelPreference, 0);
}
}
+ public static void set_telemetry_rate(int serial, int new_telemetry_rate) {
+ synchronized (backend) {
+ telemetry_rates.put(serial, new_telemetry_rate);
+ backend.putInt(String.format(telemetryRatePreferenceFormat, serial), new_telemetry_rate);
+ flush_preferences();
+ }
+ }
+
+ public static int telemetry_rate(int serial) {
+ synchronized (backend) {
+ if (telemetry_rates.containsKey(serial))
+ return telemetry_rates.get(serial);
+ int telemetry_rate = backend.getInt(String.format(telemetryRatePreferenceFormat, serial),
+ AltosLib.ao_telemetry_rate_38400);
+ telemetry_rates.put(serial, telemetry_rate);
+ return telemetry_rate;
+ }
+ }
+
+ public static void set_logfile(int serial, File new_logfile) {
+ synchronized(backend) {
+ logfiles.put(serial, new_logfile);
+ backend.putString(String.format(logfilePreferenceFormat, serial), new_logfile.getPath());
+ flush_preferences();
+ }
+ }
+
+ public static File logfile(int serial) {
+ synchronized(backend) {
+ if (logfiles.containsKey(serial))
+ return logfiles.get(serial);
+ String logfile_string = backend.getString(String.format(logfilePreferenceFormat, serial), null);
+ if (logfile_string == null)
+ return null;
+ File logfile = new File(logfile_string);
+ logfiles.put(serial, logfile);
+ return logfile;
+ }
+ }
+
public static void set_scanning_telemetry(int new_scanning_telemetry) {
synchronized (backend) {
scanning_telemetry = new_scanning_telemetry;
}
}
+ public static void set_scanning_telemetry_rate(int new_scanning_telemetry_rate) {
+ synchronized (backend) {
+ scanning_telemetry_rate = new_scanning_telemetry_rate;
+ backend.putInt(scanningTelemetryRatePreference, scanning_telemetry_rate);
+ flush_preferences();
+ }
+ }
+
+ public static int scanning_telemetry_rate() {
+ synchronized(backend) {
+ return scanning_telemetry_rate;
+ }
+ }
+
public static void set_voice(boolean new_voice) {
synchronized (backend) {
voice = new_voice;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.File;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.*;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
public class AltosReplayReader extends AltosFlightReader {
Iterator<AltosState> iterator;
File file;
+ boolean real_time;
public AltosState read() {
if (iterator.hasNext())
public void update(AltosState state) throws InterruptedException {
/* Make it run in realtime after the rocket leaves the pad */
- if (state.state > AltosLib.ao_flight_pad && state.time_change > 0)
+ if (real_time && state.state > AltosLib.ao_flight_pad && state.time_change > 0)
Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
state.set_received_time(System.currentTimeMillis());
}
public File backing_file() { return file; }
- public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
+ public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file,
+ boolean in_real_time) {
iterator = in_iterator;
file = in_file;
+ real_time = in_real_time;
name = file.getName();
}
+
+ public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
+ this(in_iterator, in_file, false);
+ }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosSpeed extends AltosUnits {
* Track flight state from telemetry or eeprom data stream
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosState implements Cloneable {
public int state;
public int flight;
public int serial;
+ public int altitude_32;
public int receiver_serial;
public boolean landed;
public boolean ascent; /* going up? */
pressure.set(p, time);
}
+ public double baro_height() {
+ double a = altitude();
+ double g = ground_altitude();
+ if (a != AltosLib.MISSING && g != AltosLib.MISSING)
+ return a - g;
+ return AltosLib.MISSING;
+ }
+
public double height() {
double k = kalman_height.value();
if (k != AltosLib.MISSING)
return k;
- double a = altitude();
- double g = ground_altitude();
- if (a != AltosLib.MISSING && g != AltosLib.MISSING)
- return a - g;
+ double b = baro_height();
+ if (b != AltosLib.MISSING)
+ return b;
+
return gps_height();
}
product = null;
serial = AltosLib.MISSING;
receiver_serial = AltosLib.MISSING;
+ altitude_32 = AltosLib.MISSING;
baro = null;
companion = null;
product = old.product;
serial = old.serial;
receiver_serial = old.receiver_serial;
+ altitude_32 = old.altitude_32;
baro = old.baro;
companion = old.companion;
firmware_version = version;
}
+ public int compare_version(String other_version) {
+ if (firmware_version == null)
+ return AltosLib.MISSING;
+ return AltosLib.compare_version(firmware_version, other_version);
+ }
+
+ private void re_init() {
+ int bt = boost_tick;
+ int rs = receiver_serial;
+ init();
+ boost_tick = bt;
+ receiver_serial = rs;
+ }
+
public void set_flight(int flight) {
/* When the flight changes, reset the state */
- if (flight != AltosLib.MISSING && flight != 0) {
+ if (flight != AltosLib.MISSING) {
if (this.flight != AltosLib.MISSING &&
this.flight != flight) {
- int bt = boost_tick;
- init();
- boost_tick = bt;
+ re_init();
}
this.flight = flight;
}
if (serial != AltosLib.MISSING) {
if (this.serial != AltosLib.MISSING &&
this.serial != serial) {
- int bt = boost_tick;
- init();
- boost_tick = bt;
+ re_init();
}
this.serial = serial;
}
receiver_serial = serial;
}
+ public boolean altitude_32() {
+ return altitude_32 == 1;
+ }
+
+ public void set_altitude_32(int altitude_32) {
+ if (altitude_32 != AltosLib.MISSING)
+ this.altitude_32 = altitude_32;
+ }
+
public int rssi() {
if (rssi == AltosLib.MISSING)
return 0;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
}
public abstract void write(PrintStream out);
+
+ public static AltosStateIterable iterable(File file) {
+ FileInputStream in;
+ try {
+ in = new FileInputStream(file);
+ } catch (Exception e) {
+ System.out.printf("Failed to open file '%s'\n", file);
+ return null;
+ }
+ if (file.getName().endsWith("telem"))
+ return new AltosTelemetryFile(in);
+ else
+ return new AltosEepromFile(in);
+ }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public interface AltosStateUpdate {
public void update_state(AltosState state) throws InterruptedException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
return telem;
}
+ public static int extend_height(AltosState state, int height_16) {
+ double compare_height;
+ int height = height_16;
+
+ if (state.gps != null && state.gps.alt != AltosLib.MISSING) {
+ compare_height = state.gps_height();
+ } else {
+ compare_height = state.height();
+ }
+
+ if (compare_height != AltosLib.MISSING) {
+ int high_bits = (int) Math.floor (compare_height / 65536.0);
+
+ height = (high_bits << 16) | (height_16 & 0xffff);
+
+ if (Math.abs(height + 65536 - compare_height) < Math.abs(height - compare_height))
+ height += 65536;
+ else if (Math.abs(height - 65536 - compare_height) < Math.abs(height - compare_height))
+ height -= 65536;
+ }
+ return height;
+ }
+
public static AltosTelemetry parse(String line) throws ParseException, AltosCRCException {
String[] word = line.split("\\s+");
int i =0;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
* g_v GPS vertical speed (integer, cm/sec)
* g_s GPS horizontal speed (integer, cm/sec)
* g_c GPS course (integer, 0-359)
+ * g_pd GPS pdop (integer * 10)
* g_hd GPS hdop (integer * 10)
* g_vd GPS vdop (integer * 10)
* g_he GPS h error (integer)
final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v";
final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g";
final static String AO_TELEM_GPS_COURSE = "g_c";
+ final static String AO_TELEM_GPS_PDOP = "g_pd";
final static String AO_TELEM_GPS_HDOP = "g_hd";
final static String AO_TELEM_GPS_VDOP = "g_vd";
final static String AO_TELEM_GPS_HERROR = "g_he";
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetryLocation extends AltosTelemetryStandard {
int climb_rate;
int course;
+ public static final int AO_GPS_MODE_ALTITUDE_24 = (1 << 0); /* Reports 24-bits of altitude */
+
public AltosTelemetryLocation(int[] bytes) {
super(bytes);
flags = uint8(5);
- altitude = int16(6);
latitude = uint32(8);
longitude = uint32(12);
year = uint8(16);
ground_speed = uint16(26);
climb_rate = int16(28);
course = uint8(30);
+
+ if ((mode & AO_GPS_MODE_ALTITUDE_24) != 0) {
+ altitude = (int8(31) << 16) | uint16(6);
+ } else
+ altitude = int16(6);
}
public void update_state(AltosState state) {
gps.ground_speed = ground_speed * 1.0e-2;
gps.course = course * 2;
gps.climb_rate = climb_rate * 1.0e-2;
- gps.hdop = hdop;
- gps.vdop = vdop;
+ gps.pdop = pdop / 10.0;
+ gps.hdop = hdop / 10.0;
+ gps.vdop = vdop / 10.0;
}
state.set_temp_gps();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
import java.util.HashMap;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetryMegaData extends AltosTelemetryStandard {
int state;
int acceleration;
int speed;
- int height;
+ int height_16;
public AltosTelemetryMegaData(int[] bytes) {
super(bytes);
- state = int8(5);
+ state = uint8(5);
v_batt = int16(6);
v_pyro = int16(8);
sense = new int[6];
for (int i = 0; i < 6; i++) {
- sense[i] = int8(10 + i) << 4;
+ sense[i] = uint8(10 + i) << 4;
sense[i] |= sense[i] >> 8;
}
acceleration = int16(26);
speed = int16(28);
- height = int16(30);
+
+ height_16 = int16(30);
}
public void update_state(AltosState state) {
state.set_ground_pressure(ground_pres);
state.set_accel_g(accel_plus_g, accel_minus_g);
- state.set_kalman(height, speed/16.0, acceleration / 16.0);
+ /* Fill in the high bits of height from recent GPS
+ * data if available, otherwise guess using the
+ * previous kalman height
+ */
+
+ state.set_kalman(extend_height(state, height_16),
+ speed/16.0, acceleration / 16.0);
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
int accel;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
int acceleration;
int speed;
- int height;
+ int height_16;
int v_batt;
int sense_a;
acceleration = int16(14);
speed = int16(16);
- height = int16(18);
+ height_16 = int16(18);
v_batt = int16(20);
sense_a = int16(22);
state.set_pressure(pres);
state.set_temperature(temp/100.0);
- state.set_kalman(height, speed/16.0, acceleration/16.0);
+ state.set_kalman(extend_height(state, height_16),
+ speed/16.0, acceleration/16.0);
state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt));
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetryMini extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetryRaw extends AltosTelemetryStandard {
public AltosTelemetryRaw(int[] bytes) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
import java.text.*;
import java.io.*;
AltosLog log;
double frequency;
int telemetry;
+ int telemetry_rate;
AltosState state = null;
+ AltosFlightReader stacked;
LinkedBlockingQueue<AltosLine> telem;
public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException {
+ if (stacked != null) {
+ state = stacked.read();
+ if (state != null)
+ return state;
+ stacked = null;
+ }
AltosLine l = telem.take();
if (l.line == null)
throw new IOException("IO error");
}
public void close(boolean interrupted) {
+
+ if (stacked != null) {
+ stacked.close(interrupted);
+ stacked = null;
+ }
+
link.remove_monitor(telem);
log.close();
try {
}
}
+ public boolean supports_telemetry_rate(int telemetry_rate) {
+ try {
+ /* Version 1.4.1.1 supports all rates, older versions don't */
+ if (link.config_data().compare_version("1.4.1.1") >= 0)
+ return true;
+
+ if (telemetry_rate == AltosLib.ao_telemetry_rate_38400)
+ return true;
+ else
+ return false;
+ } catch (InterruptedException ie) {
+ return false;
+ } catch (TimeoutException te) {
+ return true;
+ }
+ }
+
public void save_frequency() {
AltosPreferences.set_frequency(link.serial, frequency);
}
AltosPreferences.set_telemetry(link.serial, telemetry);
}
+ public void set_telemetry_rate(int in_telemetry_rate) {
+ telemetry_rate = in_telemetry_rate;
+ link.set_telemetry_rate(telemetry_rate);
+ }
+
+ public void save_telemetry_rate() {
+ AltosPreferences.set_telemetry_rate(link.serial, telemetry_rate);
+ }
+
public void set_monitor(boolean monitor) {
link.set_monitor(monitor);
}
return link.monitor_battery();
}
- public AltosTelemetryReader (AltosLink in_link)
+ public AltosTelemetryReader (AltosLink in_link, AltosFlightReader in_stacked)
throws IOException, InterruptedException, TimeoutException {
link = in_link;
+ stacked = in_stacked;
boolean success = false;
try {
log = new AltosLog(link);
set_frequency(frequency);
telemetry = AltosPreferences.telemetry(link.serial);
set_telemetry(telemetry);
+ telemetry_rate = AltosPreferences.telemetry_rate(link.serial);
+ set_telemetry_rate(telemetry_rate);
link.add_monitor(telem);
success = true;
} finally {
close(true);
}
}
+
+ private static AltosFlightReader existing_data(AltosLink link) {
+ if (link == null)
+ return null;
+
+ File file = AltosPreferences.logfile(link.serial);
+ if (file != null) {
+ AltosStateIterable iterable = AltosStateIterable.iterable(file);
+ if (iterable != null)
+ return new AltosReplayReader(iterable.iterator(), file, false);
+ }
+ return null;
+ }
+
+ public AltosTelemetryReader(AltosLink link)
+ throws IOException, InterruptedException, TimeoutException {
+ this(link, existing_data(link));
+ }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetrySatellite extends AltosTelemetryStandard {
int channels;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTelemetrySensor extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public abstract class AltosTelemetryStandard extends AltosTelemetry {
int[] bytes;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosTemperature extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public abstract class AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public interface AltosUnitsListener {
public void units_changed(boolean imperial_units);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public class AltosVoltage extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_4;
+package org.altusmetrum.altoslib_5;
public interface AltosWriter {
- public void write(AltosState state);
-
public void write(AltosStateIterable states);
public void close();
all-local: $(JAR)
clean-local:
- -rm -rf bin $(JAR)
+ -rm -rf $(JAVAROOT) altoslib_*.jar
install-altoslibJAVA: $(JAR)
@$(NORMAL_INSTALL)
Altos-Linux-*.sh
Altos-Mac-*.zip
Altos-Windows-*.exe
-altos.desktop
+.desktop
*.dll
*.dylib
*.so
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class Altos extends AltosUILib {
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosAscent extends AltosUIFlightTab {
JLabel cur, max;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
private AltosFlightInfoTableModel model;
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosConfig implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosConfigPyroUI
extends AltosUIDialog
"0.050", "0.100", "0.250", "0.500", "1.0", "2.0"
};
+ boolean initializing;
+
public void set_pyro_firing_time(double new_pyro_firing_time) {
+ initializing = true;
pyro_firing_time_value.setSelectedItem(Double.toString(new_pyro_firing_time));
pyro_firing_time_value.setEnabled(new_pyro_firing_time >= 0);
+ initializing = false;
}
public double get_pyro_firing_time() throws AltosConfigDataException {
}
public void set_dirty() {
- owner.set_dirty();
+ if (!initializing)
+ owner.set_dirty();
}
public void itemStateChanged(ItemEvent e) {
- owner.set_dirty();
+ if (!initializing)
+ owner.set_dirty();
}
public void changedUpdate(DocumentEvent e) {
- owner.set_dirty();
+ if (!initializing)
+ owner.set_dirty();
}
public void insertUpdate(DocumentEvent e) {
- owner.set_dirty();
+ if (!initializing)
+ owner.set_dirty();
}
public void removeUpdate(DocumentEvent e) {
- owner.set_dirty();
+ if (!initializing)
+ owner.set_dirty();
}
public void units_changed(boolean imperial_units) {
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosConfigTD implements ActionListener {
int_ref radio_calibration;
int_ref radio_setting;
int_ref radio_frequency;
+ int_ref telemetry_rate;
string_ref config_version;
string_ref version;
string_ref product;
config_ui.set_version(version.get());
config_ui.set_radio_frequency(frequency());
config_ui.set_radio_calibration(radio_calibration.get());
+ config_ui.set_telemetry_rate(telemetry_rate.get());
config_ui.set_clean();
if (!made_visible) {
made_visible = true;
get_int(line, "Radio cal:", radio_calibration);
get_int(line, "Frequency:", radio_frequency);
get_int(line, "Radio setting:", radio_setting);
+ get_int(line, "Telemetry rate:", telemetry_rate);
get_string(line,"software-version", version);
get_string(line,"product", product);
}
radio_setting.set(0);
radio_frequency.set(0);
radio_calibration.set(1186611);
+ telemetry_rate.set(Altos.ao_telemetry_rate_38400);
config_version.set("0.0");
version.set("unknown");
product.set("unknown");
}
}
+ synchronized int telemetry_rate() {
+ return telemetry_rate.get();
+ }
+
+ synchronized void set_telemetry_rate(int new_telemetry_rate){
+ int rate = telemetry_rate.get();
+
+ if (rate >= 0)
+ telemetry_rate.set(new_telemetry_rate);
+ }
+
final static int serial_mode_read = 0;
final static int serial_mode_save = 1;
final static int serial_mode_reboot = 2;
if (!config_version.get().equals("0.0"))
break;
been_there = true;
- config.serial_line.printf("C\n ");
- config.serial_line.flush_input();
+ if (config != null && config.serial_line != null) {
+ config.serial_line.printf("C\n ");
+ config.serial_line.flush_input();
+ }
}
} catch (InterruptedException ie) {
}
* available firmware version might place on the actual frequency
*/
config.set_frequency(AltosPreferences.frequency(serial.get()));
+ config.set_telemetry_rate(AltosPreferences.telemetry_rate(serial.get()));
config.process_line("all finished");
}
if (frequency != 0)
AltosPreferences.set_frequency(serial.get(),
frequency);
+ AltosPreferences.set_telemetry_rate(serial.get(),
+ telemetry_rate());
}
public void run () {
}
void abort() {
- serial_line.close();
- serial_line = null;
+ if (serial_line != null) {
+ serial_line.close();
+ serial_line = null;
+ }
JOptionPane.showMessageDialog(owner,
String.format("Connection to \"%s\" failed",
device.toShortString()),
void save_data() {
double freq = config_ui.radio_frequency();
set_frequency(freq);
+ int telemetry_rate = config_ui.telemetry_rate();
+ set_telemetry_rate(telemetry_rate);
run_serial_thread(serial_mode_save);
}
radio_setting = new int_ref(0);
radio_frequency = new int_ref(0);
radio_calibration = new int_ref(1186611);
+ telemetry_rate = new int_ref(AltosLib.ao_telemetry_rate_38400);
config_version = new string_ref("0.0");
version = new string_ref("unknown");
product = new string_ref("unknown");
}
}
}
-}
\ No newline at end of file
+}
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosConfigTDUI
extends AltosUIDialog
JLabel frequency_label;
JLabel radio_calibration_label;
JLabel radio_frequency_label;
+ JLabel rate_label;
public boolean dirty;
JLabel product_value;
JLabel version_value;
JLabel serial_value;
- AltosFreqList radio_frequency_value;
+ AltosUIFreqList radio_frequency_value;
JLabel radio_calibration_value;
+ AltosUIRateList rate_value;
JButton save;
JButton reset;
ActionListener listener;
-
/* A window listener to catch closing events and tell the config code */
class ConfigListener extends WindowAdapter {
AltosConfigTDUI ui;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_frequency_value = new AltosFreqList();
+ radio_frequency_value = new AltosUIFreqList();
radio_frequency_value.addItemListener(this);
pane.add(radio_frequency_value, c);
radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
radio_calibration_value = new JLabel(String.format("%d", 1186611));
pane.add(radio_calibration_value, c);
+ /* Telemetry Rate */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 7;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ rate_label = new JLabel("Telemetry Rate:");
+ pane.add(rate_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = 7;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ rate_value = new AltosUIRateList();
+ pane.add(rate_value, c);
+
/* Buttons */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 12;
radio_calibration_value.setText(String.format("%d", calibration));
}
+ public int telemetry_rate() {
+ return rate_value.getSelectedIndex();
+ }
+
+ public void set_telemetry_rate(int rate) {
+ rate_value.setSelectedIndex(rate);
+ }
+
public void set_clean() {
dirty = false;
}
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosConfigUI
extends AltosUIDialog
JLabel radio_calibration_label;
JLabel radio_frequency_label;
JLabel radio_enable_label;
+ JLabel rate_label;
JLabel aprs_interval_label;
+ JLabel aprs_ssid_label;
JLabel flight_log_max_label;
JLabel ignite_mode_label;
JLabel pad_orientation_label;
JComboBox<String> main_deploy_value;
JComboBox<String> apogee_delay_value;
JComboBox<String> apogee_lockout_value;
- AltosFreqList radio_frequency_value;
+ AltosUIFreqList radio_frequency_value;
JTextField radio_calibration_value;
JRadioButton radio_enable_value;
+ AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
+ JComboBox<Integer> aprs_ssid_value;
JComboBox<String> flight_log_max_value;
JComboBox<String> ignite_mode_value;
JComboBox<String> pad_orientation_value;
"10"
};
+ static Integer[] aprs_ssid_values = {
+ 0, 1, 2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+ };
+
static String[] beep_values = {
"3750",
"4000",
radio_enable_value.setToolTipText("Firmware version does not support disabling radio");
}
+ void set_rate_tool_tip() {
+ if (rate_value.isEnabled())
+ rate_value.setToolTipText("Select telemetry baud rate");
+ else
+ rate_value.setToolTipText("Firmware version does not support variable telemetry rates");
+ }
+
void set_aprs_interval_tool_tip() {
if (aprs_interval_value.isEnabled())
aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");
aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
}
+ void set_aprs_ssid_tool_tip() {
+ if (aprs_ssid_value.isEnabled())
+ aprs_interval_value.setToolTipText("Set the APRS SSID (secondary station identifier)");
+ else if (aprs_interval_value.isEnabled())
+ aprs_interval_value.setToolTipText("Software version doesn't support setting the APRS SSID");
+ else
+ aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
+ }
+
void set_flight_log_max_tool_tip() {
if (flight_log_max_value.isEnabled())
flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_frequency_value = new AltosFreqList();
+ radio_frequency_value = new AltosUIFreqList();
radio_frequency_value.addItemListener(this);
pane.add(radio_frequency_value, c);
radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
set_radio_enable_tool_tip();
row++;
+ /* Telemetry Rate */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ rate_label = new JLabel("Telemetry baud rate:");
+ pane.add(rate_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ rate_value = new AltosUIRateList();
+ rate_value.addItemListener(this);
+ pane.add(rate_value, c);
+ set_rate_tool_tip();
+ row++;
+
/* APRS interval */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = row;
set_aprs_interval_tool_tip();
row++;
+ /* APRS SSID */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ aprs_ssid_label = new JLabel("APRS SSID:");
+ pane.add(aprs_ssid_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ aprs_ssid_value = new JComboBox<Integer>(aprs_ssid_values);
+ aprs_ssid_value.setEditable(false);
+ aprs_ssid_value.addItemListener(this);
+ aprs_ssid_value.setMaximumRowCount(aprs_ssid_values.length);
+ pane.add(aprs_ssid_value, c);
+ set_aprs_ssid_tool_tip();
+ row++;
+
/* Callsign */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = row;
serial_value.setText(String.format("%d", serial));
}
+ public void set_altitude_32(int altitude_32) {
+ }
+
public void set_main_deploy(int new_main_deploy) {
main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy));
main_deploy_value.setEnabled(new_main_deploy >= 0);
+
+ main_deploy_value.setVisible(new_main_deploy >= 0);
+ main_deploy_label.setVisible(new_main_deploy >= 0);
+
}
public int main_deploy() {
}
public void units_changed(boolean imperial_units) {
+ boolean was_dirty = dirty;
+
String v = main_deploy_value.getSelectedItem().toString();
main_deploy_label.setText(get_main_deploy_label());
set_main_deploy_values();
set_tracker_motion_values();
set_tracker_motion((int) (AltosConvert.height.parse(motion, !imperial_units) + 0.5));
}
+
+ if (!was_dirty)
+ set_clean();
}
public void set_apogee_delay(int new_apogee_delay) {
+ apogee_delay_value.setVisible(new_apogee_delay >= 0);
+ apogee_delay_label.setVisible(new_apogee_delay >= 0);
+
apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
apogee_delay_value.setEnabled(new_apogee_delay >= 0);
}
public void set_apogee_lockout(int new_apogee_lockout) {
apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout));
apogee_lockout_value.setEnabled(new_apogee_lockout >= 0);
+
+ apogee_lockout_value.setVisible(new_apogee_lockout >= 0);
+ apogee_lockout_label.setVisible(new_apogee_lockout >= 0);
}
public int apogee_lockout() throws AltosConfigDataException {
}
public void set_radio_frequency(double new_radio_frequency) {
+ radio_frequency_label.setVisible(new_radio_frequency >= 0);
radio_frequency_value.set_frequency(new_radio_frequency);
}
public void set_radio_calibration(int new_radio_calibration) {
radio_calibration_value.setVisible(new_radio_calibration >= 0);
+ radio_calibration_label.setVisible(new_radio_calibration >= 0);
+
if (new_radio_calibration < 0)
radio_calibration_value.setText("Disabled");
else
}
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);
+
if (new_radio_enable >= 0) {
radio_enable_value.setSelected(new_radio_enable > 0);
radio_enable_value.setEnabled(true);
} else {
radio_enable_value.setSelected(true);
- radio_enable_value.setVisible(radio_frequency() > 0);
radio_enable_value.setEnabled(false);
}
set_radio_enable_tool_tip();
return -1;
}
+ public void set_telemetry_rate(int new_rate) {
+ rate_label.setVisible(new_rate >= 0);
+
+ rate_value.set_rate(new_rate);
+ }
+
+ public int telemetry_rate() {
+ return rate_value.rate();
+ }
+
public void set_callsign(String new_callsign) {
callsign_value.setVisible(new_callsign != null);
+ callsign_label.setVisible(new_callsign != null);
+
callsign_value.setText(new_callsign);
}
}
public void set_flight_log_max(int new_flight_log_max) {
+ flight_log_max_value.setVisible(new_flight_log_max >= 0);
+ flight_log_max_label.setVisible(new_flight_log_max >= 0);
+
flight_log_max_value.setSelectedItem(flight_log_max_label(new_flight_log_max));
flight_log_max = new_flight_log_max;
set_flight_log_max_tool_tip();
}
public void set_ignite_mode(int new_ignite_mode) {
+ ignite_mode_value.setVisible(new_ignite_mode >= 0);
+ ignite_mode_label.setVisible(new_ignite_mode >= 0);
+
if (new_ignite_mode >= ignite_mode_values.length)
new_ignite_mode = 0;
if (new_ignite_mode < 0) {
public void set_pad_orientation(int new_pad_orientation) {
+ pad_orientation_value.setVisible(new_pad_orientation >= 0);
+ pad_orientation_label.setVisible(new_pad_orientation >= 0);
+
if (new_pad_orientation >= pad_orientation_values.length)
new_pad_orientation = 0;
- if (new_pad_orientation < 0) {
- pad_orientation_value.setVisible(false);
+ if (new_pad_orientation < 0)
new_pad_orientation = 0;
- } else {
- pad_orientation_value.setVisible(true);
- }
pad_orientation_value.setSelectedIndex(new_pad_orientation);
set_pad_orientation_tool_tip();
}
}
public void set_beep(int new_beep) {
+ beep_value.setVisible(new_beep >= 0);
+ beep_label.setVisible(new_beep >= 0);
+
int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5);
for (int i = 0; i < beep_values.length; i++)
if (new_beep == AltosConvert.beep_freq_to_value(Integer.parseInt(beep_values[i]))) {
}
public void set_tracker_motion(int tracker_motion) {
+ tracker_motion_label.setVisible(tracker_motion >= 0);
+ tracker_motion_value.setVisible(tracker_motion >= 0);
+
if (tracker_motion < 0) {
- tracker_motion_label.setVisible(false);
- tracker_motion_value.setVisible(false);
+ tracker_motion_value.setEnabled(false);
} else {
- tracker_motion_label.setVisible(true);
- tracker_motion_value.setVisible(true);
+ tracker_motion_value.setEnabled(true);
tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
}
}
}
public void set_tracker_interval(int tracker_interval) {
+ tracker_interval_label.setVisible(tracker_interval >= 0);
+ tracker_interval_value.setVisible(tracker_interval >= 0);
+
if (tracker_interval< 0) {
- tracker_interval_label.setVisible(false);
- tracker_interval_value.setVisible(false);
+ tracker_interval_value.setEnabled(false);
} else {
- tracker_interval_label.setVisible(true);
- tracker_interval_value.setVisible(true);
+ tracker_interval_value.setEnabled(true);
tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
}
}
}
public void set_aprs_interval(int new_aprs_interval) {
+ aprs_interval_value.setVisible(new_aprs_interval >= 0);
+ aprs_interval_label.setVisible(new_aprs_interval >= 0);
+
String s;
if (new_aprs_interval <= 0)
else
s = Integer.toString(new_aprs_interval);
aprs_interval_value.setSelectedItem(s);
- aprs_interval_value.setVisible(new_aprs_interval >= 0);
set_aprs_interval_tool_tip();
}
return 0;
return parse_int("aprs interval", s, false);
}
+
+ public void set_aprs_ssid(int new_aprs_ssid) {
+ aprs_ssid_value.setVisible(new_aprs_ssid >= 0);
+ aprs_ssid_label.setVisible(new_aprs_ssid >= 0);
+
+ aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid));
+ set_aprs_ssid_tool_tip();
+ }
+
+ public int aprs_ssid() throws AltosConfigDataException {
+ Integer i = (Integer) aprs_ssid_value.getSelectedItem();
+ return i;
+ }
}
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosConfigureUI
extends AltosUIConfigure
row++;
}
+ boolean has_bluetooth;
+
public void add_bluetooth() {
JButton manage_bluetooth = new JButton("Manage Bluetooth");
manage_bluetooth.addActionListener(new ActionListener() {
});
pane.add(manage_bluetooth, constraints(0, 2));
/* in the same row as add_frequencies, so don't bump row */
+ has_bluetooth = true;
}
public void add_frequencies() {
}
});
manage_frequencies.setToolTipText("Configure which values are shown in frequency menus");
- pane.add(manage_frequencies, constraints(2, 1));
+ if (has_bluetooth)
+ pane.add(manage_frequencies, constraints(2, 1));
+ else
+ pane.add(manage_frequencies, constraints(0, 3));
row++;
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosDescent extends AltosUIFlightTab {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
import java.text.*;
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosFlightStatusTableModel extends AbstractTableModel {
private String[] columnNames = {
package altosui;
import java.awt.event.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosFlightStatusUpdate implements ActionListener {
import javax.swing.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
AltosVoice voice;
exit_on_close = true;
}
- Container bag;
- AltosFreqList frequencies;
- JComboBox<String> telemetries;
- JLabel telemetry;
+ Container bag;
+ AltosUIFreqList frequencies;
+ AltosUIRateList rates;
+ AltosUITelemetryList telemetries;
+ JLabel telemetry;
ActionListener show_timer;
/* Stick channel selector at top of table for telemetry monitoring */
if (serial >= 0) {
- // Channel menu
- frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial));
+ // Frequency menu
+ frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
frequencies.set_product("Monitor");
frequencies.set_serial(serial);
frequencies.addActionListener(new ActionListener() {
c.anchor = GridBagConstraints.WEST;
bag.add (frequencies, c);
- // Telemetry format menu
+ // Telemetry rate list
+ rates = new AltosUIRateList(AltosUIPreferences.telemetry_rate(serial));
+ rates.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ int rate = rates.rate();
+ try {
+ reader.set_telemetry_rate(rate);
+ } catch (TimeoutException te) {
+ } catch (InterruptedException ie) {
+ }
+ reader.save_telemetry_rate();
+ }
+ });
+ rates.setEnabled(reader.supports_telemetry_rate(AltosLib.ao_telemetry_rate_2400));
+ c.gridx = 1;
+ c.gridy = 0;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.insets = new Insets(3, 3, 3, 3);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ bag.add (rates, c);
+
+ // Telemetry format list
if (reader.supports_telemetry(Altos.ao_telemetry_standard)) {
- telemetries = new JComboBox<String>();
- for (int i = 1; i <= Altos.ao_telemetry_max; i++)
- telemetries.addItem(Altos.telemetry_name(i));
- int telemetry = AltosPreferences.telemetry(serial);
- if (telemetry <= Altos.ao_telemetry_off ||
- telemetry > Altos.ao_telemetry_max)
- telemetry = Altos.ao_telemetry_standard;
- telemetries.setSelectedIndex(telemetry - 1);
- telemetries.setMaximumRowCount(Altos.ao_telemetry_max);
- telemetries.setPreferredSize(null);
- telemetries.revalidate();
+ telemetries = new AltosUITelemetryList(serial);
telemetries.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- int telemetry = telemetries.getSelectedIndex() + 1;
+ int telemetry = telemetries.get_selected();
reader.set_telemetry(telemetry);
reader.save_telemetry();
}
});
- c.gridx = 1;
+ c.gridx = 2;
c.gridy = 0;
c.weightx = 0;
c.weighty = 0;
version = "Telemetry: None";
telemetry = new JLabel(version);
- c.gridx = 1;
+ c.gridx = 2;
c.gridy = 0;
c.weightx = 0;
c.weighty = 0;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
- c.gridwidth = 2;
+ c.gridwidth = 3;
bag.add(flightStatus, c);
- c.gridwidth = 1;
/* The rest of the window uses a tabbed pane to
* show one of the alternate data views
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
- c.gridwidth = 2;
bag.add(pane, c);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import java.io.*;
import java.util.concurrent.*;
import java.util.Arrays;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
AltosDevice device;
AltosPad pad;
AltosInfoTable flightInfo;
AltosFlightStatus flightStatus;
+ AltosIgnitor ignitor;
AltosIdleMonitor thread;
int serial;
boolean remote;
+ boolean has_ignitor;
void stop_display() {
if (thread != null) {
public void show(AltosState state, AltosListenerState listener_state) {
status_update.saved_state = state;
+ if (ignitor.should_show(state)) {
+ if (!has_ignitor) {
+ pane.add("Ignitor", ignitor);
+ has_ignitor = true;
+ }
+ } else {
+ if (has_ignitor) {
+ pane.remove(ignitor);
+ has_ignitor = false;
+ }
+ }
// try {
pad.show(state, listener_state);
flightStatus.show(state, listener_state);
flightInfo.show(state, listener_state);
+ ignitor.show(state, listener_state);
// } catch (Exception e) {
// System.out.print("Show exception " + e);
// }
}
Container bag;
- AltosFreqList frequencies;
+ AltosUIFreqList frequencies;
JTextField callsign_value;
/* DocumentListener interface methods */
/* Stick frequency selector at top of table for telemetry monitoring */
if (remote && serial >= 0) {
// Frequency menu
- frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial));
+ frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
frequencies.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
double frequency = frequencies.frequency();
flightInfo = new AltosInfoTable();
pane.add("Table", new JScrollPane(flightInfo));
+ ignitor = new AltosIgnitor();
+
/* Make the tabbed pane use the rest of the window space */
bag.add(pane, constraints(0, 3, GridBagConstraints.BOTH));
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosIgniteUI
extends AltosUIDialog
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosIgnitor extends AltosUIFlightTab {
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosLanded extends AltosUIFlightTab implements ActionListener {
return "Landed";
}
+ public void show(AltosState state, AltosListenerState listener_state) {
+ super.show(state, listener_state);
+ if (reader.backing_file() != null)
+ graph.setEnabled(true);
+ }
+
public AltosLanded(AltosFlightReader in_reader) {
reader = in_reader;
import java.io.*;
import java.util.concurrent.*;
import java.awt.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosLaunch {
AltosDevice device;
import java.io.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
class FireButton extends JButton {
protected void processMouseEvent(MouseEvent e) {
package altosui;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosPad extends AltosUIFlightTab {
}
}
+ boolean report_pad(AltosState state) {
+ if ((state.state == AltosLib.ao_flight_stateless ||
+ state.state < AltosLib.ao_flight_pad) &&
+ state.gps != null &&
+ state.gps.lat != AltosLib.MISSING)
+ {
+ return false;
+ }
+ return true;
+ }
+
class PadLat extends AltosUIIndicator {
double last_lat = AltosLib.MISSING - 1;
String label = null;
if (state != null) {
- if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.lat != AltosLib.MISSING) {
- lat = state.gps.lat;
- label = "Latitude";
- } else {
+ if (report_pad(state)) {
lat = state.pad_lat;
label = "Pad Latitude";
+ } else {
+ lat = state.gps.lat;
+ label = "Latitude";
}
}
if (lat != last_lat) {
String label = null;
if (state != null) {
- if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.lon != AltosLib.MISSING) {
- lon = state.gps.lon;
- label = "Longitude";
- } else {
+ if (report_pad(state)) {
lon = state.pad_lon;
label = "Pad Longitude";
+ } else {
+ lon = state.gps.lon;
+ label = "Longitude";
}
}
if (lon != last_lon) {
String label = null;
if (state != null) {
- if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.alt != AltosLib.MISSING) {
- alt = state.gps.alt;
- label = "Altitude";
- } else {
+ if (report_pad(state)) {
alt = state.pad_alt;
label = "Pad Altitude";
+ } else {
+ alt = state.gps.alt;
+ label = "Altitude";
}
}
if (alt != last_alt) {
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class AltosUI extends AltosUIFrame {
public AltosVoice voice = new AltosVoice();
return b;
}
+ /* OSXAdapter interfaces */
+ public void macosx_file_handler(String path) {
+ process_graph(new File(path));
+ }
+
+ public void macosx_quit_handler() {
+ System.exit(0);
+ }
+
+ public void macosx_preferences_handler() {
+ ConfigureAltosUI();
+ }
+
public AltosUI() {
load_library(null);
+ register_for_macosx_events();
+
AltosUIPreferences.set_component(this);
pane = getContentPane();
import java.io.File;
import java.util.prefs.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import javax.swing.filechooser.FileSystemView;
public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
- <string>AltosUIIcon.icns</string>
+ <string>altusmetrum-altosui.icns</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>Telemetry</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>application-vnd.altusmetrum.telemetry.icns</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>telem</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>Eeprom</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>application-vnd.altusmetrum.eeprom.icns</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>eeprom</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ </array>
<key>Java</key>
<dict>
<key>MainClass</key>
Delete $2
FunctionEnd
-Function DetectJRE
+Function DoDetectJRE
+
+ DetailPrint "Desired Java version ${JRE_VERSION}"
+
+ ; Check in HKCU for CurrentVersion
+
+ ClearErrors
+ ReadRegStr $2 HKCU "SOFTWARE\JavaSoft\Java Runtime Environment" \
+ "CurrentVersion"
+
+ IfErrors hklm_version
+
+ DetailPrint "HKEY_CURRENT_USER Java version $2"
+
+ ${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"
+
+ IfErrors hkcu_any
- DetailPrint "Desired Java version ${JRE_VERSION}"
- DetailPrint "Actual Java version $2"
+ DetailPrint "HKEY_LOCAL_MACHINE Java version $2"
${VersionCompare} $2 ${JRE_VERSION} $3
- IntCmp $3 1 done done
+ IntCmp $3 1 yes yes no
- Call GetJRE
+hkcu_any:
+
+ ; 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
+
+yes:
+ StrCpy $0 2
+ Goto done
+
+maybe:
+ StrCpy $0 1
+ Goto done
+
+no:
+ StrCpy $0 0
+ Goto done
done:
FunctionEnd
+
+var dialog
+var hwnd
+var null
+
+var install
+var quit
+var skip
+
+Function DetectJRE
+
+ Call DoDetectJRE
+
+ IntCmp $0 1 ask_maybe ask_no yes
+
+ask_no:
+ StrCpy $0 "No Java detected. Download and install?"
+ Goto ask
+
+ask_maybe:
+ StrCpy $0 "Cannot determine installed Java version. Download and install?"
+ Goto ask
+
+ask:
+ MessageBox MB_YESNOCANCEL $0 IDYES do_java IDNO skip_java
+
+bail:
+ Abort
+
+do_java:
+ Call GetJRE
+
+
+skip_java:
+yes:
+
+FunctionEnd
--- /dev/null
+!define SHCNE_ASSOCCHANGED 0x08000000
+!define SHCNF_IDLIST 0
+
+Function RefreshShellIcons
+ ; By jerome tremblay - april 2003
+ ${DisableX64FSRedirection}
+ System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
+FunctionEnd
+
+Function un.RefreshShellIcons
+ ; By jerome tremblay - april 2003
+ ${DisableX64FSRedirection}
+ System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (${SHCNE_ASSOCCHANGED}, ${SHCNF_IDLIST}, 0, 0)'
+FunctionEnd
altos.dll
desktopdir = $(datadir)/applications
-desktop_file = altos.desktop
+desktop_file = altusmetrum-altosui.desktop
desktop_SCRIPTS = $(desktop_file)
JAR=altosui.jar
FATJAR=altosui-fat.jar
# Icons
-ICONDIR=$(top_srcdir)/icon
+ICONDIR=../icon
JAVA_ICONS=\
- $(ICONDIR)/altus-metrum-16.png \
- $(ICONDIR)/altus-metrum-32.png \
- $(ICONDIR)/altus-metrum-48.png \
- $(ICONDIR)/altus-metrum-64.png \
- $(ICONDIR)/altus-metrum-128.png \
- $(ICONDIR)/altus-metrum-256.png
+ $(ICONDIR)/altusmetrum-altosui-16.png \
+ $(ICONDIR)/altusmetrum-altosui-32.png \
+ $(ICONDIR)/altusmetrum-altosui-48.png \
+ $(ICONDIR)/altusmetrum-altosui-64.png \
+ $(ICONDIR)/altusmetrum-altosui-128.png\
+ $(ICONDIR)/altusmetrum-altosui-256.png
# icon base names for jar
-ICONJAR= -C $(ICONDIR) altus-metrum-16.png \
- -C $(ICONDIR) altus-metrum-32.png \
- -C $(ICONDIR) altus-metrum-48.png \
- -C $(ICONDIR) altus-metrum-64.png \
- -C $(ICONDIR) altus-metrum-128.png \
- -C $(ICONDIR) altus-metrum-256.png
-
-WINDOWS_ICON=$(ICONDIR)/altus-metrum.ico
-MACOSX_ICON=$(ICONDIR)/AltosUIIcon.icns
+ICONJAR= \
+ -C $(ICONDIR) altusmetrum-altosui-16.png \
+ -C $(ICONDIR) altusmetrum-altosui-32.png \
+ -C $(ICONDIR) altusmetrum-altosui-48.png \
+ -C $(ICONDIR) altusmetrum-altosui-64.png \
+ -C $(ICONDIR) altusmetrum-altosui-128.png\
+ -C $(ICONDIR) altusmetrum-altosui-256.png
+
+WINDOWS_ICONS =\
+ $(ICONDIR)/altusmetrum-altosui.ico \
+ $(ICONDIR)/altusmetrum-altosui.exe
+ $(ICONDIR)/application-vnd.altusmetrum.eeprom.ico \
+ $(ICONDIR)/application-vnd.altusmetrum.eeprom.exe \
+ $(ICONDIR)/application-vnd.altusmetrum.telemetry.ico \
+ $(ICONDIR)/application-vnd.altusmetrum.telemetry.exe
+
+MACOSX_ICONS =\
+ $(ICONDIR)/altusmetrum-altosui.icns \
+ $(ICONDIR)/application-vnd.altusmetrum.eeprom.icns \
+ $(ICONDIR)/application-vnd.altusmetrum.telemetry.icns
+
+LINUX_ICONS =\
+ $(ICONDIR)/altusmetrum-altosui.svg \
+ $(ICONDIR)/application-vnd.altusmetrum.eeprom.svg \
+ $(ICONDIR)/application-vnd.altusmetrum.telemetry.svg
+
+LINUX_MIMETYPE =\
+ $(ICONDIR)/org-altusmetrum-mimetypes.xml
# Firmware
FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
FIRMWARE_EMINI_1_0=$(top_srcdir)/src/easymini-v1.0/easymini-v1.0-$(VERSION).ihx
FIRMWARE_EMINI=$(FIRMWARE_EMINI_1_0)
+FIRMWARE_EMEGA_1_0=$(top_srcdir)/src/easymega-v1.0/easymega-v1.0-$(VERSION).ihx
+FIRMWARE_EMEGA=$(FIRMWARE_EMEGA_1_0)
+
FIRMWARE_TGPS_1_0=$(top_srcdir)/src/telegps-v1.0/telegps-v1.0-$(VERSION).ihx
FIRMWARE_TGPS=$(FIRMWARE_TGPS_1_0)
-FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) $(FIRMWARE_TBT) $(FIRMWARE_TMEGA) $(FIRMWARE_EMINI) $(FIRMWARE_TGPS)
+FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) $(FIRMWARE_TBT) $(FIRMWARE_TMEGA) $(FIRMWARE_EMINI) $(FIRMWARE_TGPS) $(FIRMWARE_EMEGA)
ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf
ALTOS_DOC=$(top_srcdir)/doc/altos.pdf
LINUX_LIBS=libaltos32.so libaltos64.so
-LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC) altos.desktop.in ../icon/altusmetrum.svg
+LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC) $(desktop_file).in $(LINUX_ICONS) $(LINUX_MIMETYPE)
LINUX_EXTRA=altosui-fat
MACOSX_INFO_PLIST=Info.plist
-MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf $(MACOSX_ICON)
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf $(MACOSX_ICONS)
MACOSX_EXTRA=$(FIRMWARE)
-WINDOWS_FILES=$(FAT_FILES) $(FIRMWARE) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(WINDOWS_ICON)
+WINDOWS_FILES=$(FAT_FILES) $(FIRMWARE) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(WINDOWS_ICONS)
all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb
-rm -rf classes $(JAR) $(FATJAR) \
$(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) \
$(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log altos-windows.nsi \
- altosui altosui-test altosui-jdb macosx linux
+ altosui altosui-test altosui-jdb macosx linux *.desktop
EXTRA_DIST = $(desktop_file).in
$(desktop_file): $(desktop_file).in
- sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/altos.desktop.in > $@
+ sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/$(desktop_file).in > $@
chmod +x $@
if FATINSTALL
fat: $(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) $(WINDOWS_DIST)
endif
-
altosuidir=$(datadir)/java
install-altosuiJAVA: altosui.jar
cp -a $(DOC) macosx/Doc
cp -p Info.plist macosx/AltosUI.app/Contents
mkdir -p macosx/AltOS-$(VERSION) macosx/AltosUI.app/Contents/Resources/Java
- cp -p $(MACOSX_ICON) macosx/AltosUI.app/Contents/Resources
+ cp -p $(MACOSX_ICONS) macosx/AltosUI.app/Contents/Resources
cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar
cp -p libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java
cp -p $(ALTOSLIB_CLASS) macosx/AltosUI.app/Contents/Resources/Java
cp -p $(MACOSX_EXTRA) macosx/AltOS-$(VERSION)
genisoimage -D -V AltOS-$(VERSION) -no-pad -r -apple -o $@ macosx
-$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi
+$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi Instdrv/NSIS/Includes/java.nsh
-rm -f $@
makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi || (cat altos-windows.log && exit 1)
!addincludedir Instdrv/NSIS/Includes
!include x64.nsh
!include java.nsh
+!include refresh-sh.nsh
-!define PRODUCT_NAME "Altus Metrum Windows Software"
+!define REG_NAME "Altus Metrum"
+!define PROG_ID_TELEM "altusmetrum.altosui.telem.1"
+!define PROG_ID_EEPROM "altusmetrum.altosui.eeprom.1"
+!define FAT_NAME "altosui-fat.jar"
+!define WIN_APP_ICON "altusmetrum-altosui.ico"
+!define WIN_APP_EXE "altusmetrum-altosui.exe"
+!define WIN_TELEM_EXE "application-vnd.altusmetrum.telemetry.exe"
+!define WIN_EEPROM_EXE "application-vnd.altusmetrum.eeprom.exe"
-Name "Altus Metrum Installer"
+Name "${REG_NAME} Installer"
; Default install directory
InstallDir "$PROGRAMFILES\AltusMetrum"
; Tell the installer where to re-install a new version
-InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+InstallDirRegKey HKLM "Software\${REG_NAME}" "Install_Dir"
LicenseText "GNU General Public License Version 2"
LicenseData "../COPYING"
ShowInstDetails Show
-ComponentText "Altus Metrum Software and Driver Installer"
+ComponentText "${REG_NAME} Software and Driver Installer"
Function .onInit
DetailPrint "Checking host operating system"
${EndIf}
FunctionEnd
+Function un.onInit
+ DetailPrint "Checking host operating system"
+ ${If} ${RunningX64}
+ DetailPrint "Installer running on 64-bit host"
+ SetRegView 64
+ StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+ ${DisableX64FSRedirection}
+ ${EndIf}
+FunctionEnd
+
; Pages to present
Page license
SectionEnd
-Section "AltosUI Application"
+Section "${REG_NAME} Application"
Call DetectJRE
SetOutPath $INSTDIR
- File "altosui-fat.jar"
+ File "${FAT_NAME}"
File "altoslib_@ALTOSLIB_VERSION@.jar"
File "altosuilib_@ALTOSUILIB_VERSION@.jar"
File "cmudict04.jar"
File "*.dll"
- File "../icon/*.ico"
+ File "../icon/${WIN_APP_ICON}"
- CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$SYSDIR\javaw.exe" "-jar altosui-fat.jar" "$INSTDIR\altus-metrum.ico"
+ CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
-Section "AltosUI Desktop Shortcut"
- CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico"
+Section "${REG_NAME} Desktop Shortcut"
+ CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
-Section "TeleMetrum, TeleDongle and TeleBT Firmware"
+Section "Firmware"
SetOutPath $INSTDIR
File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
File "../src/telemega-v1.0/telemega-v1.0-${VERSION}.ihx"
File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
+ File "../src/easymega-v1.0/easymega-v1.0-${VERSION}.ihx"
SectionEnd
File "../doc/telemini.pdf"
SectionEnd
+Section "File Associations"
+
+ ${DisableX64FSRedirection}
+
+ SetOutPath $INSTDIR
+
+ File "../icon/${WIN_APP_EXE}"
+ File "../icon/${WIN_TELEM_EXE}"
+ File "../icon/${WIN_EEPROM_EXE}"
+
+ DeleteRegKey HKCR "${PROG_ID_TELEM}"
+ DeleteRegKey HKCR "${PROG_ID_EEPROM}"
+
+ DeleteRegKey HKCR ".eeprom\${PROG_ID_EEPROM}"
+ DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
+ DeleteRegKey HKCR ".telem\${PROG_ID_EEPROM}"
+ DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
+
+ ; .eeprom elements
+
+ WriteRegStr HKCR "${PROG_ID_EEPROM}" "" "Altus Metrum Log File"
+ WriteRegStr HKCR "${PROG_ID_EEPROM}" "FriendlyTypeName" "Altus Metrum Log File"
+ WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer" "" "${PROG_ID_EEPROM}"
+ WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" "" '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
+ WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+ WriteRegStr HKCR ".eeprom" "" "${PROG_ID_EEPROM}"
+ WriteRegStr HKCR ".eeprom" "PerceivedType" "Altus Metrum Log File"
+ WriteRegStr HKCR ".eeprom" "Content Type" "application/vnd.altusmetrum.eeprom"
+
+ WriteRegStr HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}" ""
+ WriteRegStr HKCR ".eeprom\${PROG_ID_EEPROM}" "" "${REG_NAME}"
+
+ ; .telem elements
+
+ WriteRegStr HKCR "${PROG_ID_TELEM}" "" "Altus Metrum Telemetry File"
+ WriteRegStr HKCR "${PROG_ID_TELEM}" "FriendlyTypeName" "Altus Metrum Telemetry File"
+ WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer" "" "${PROG_ID_TELEM}"
+ WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" "" '"$INSTDIR\${WIN_TELEM_EXE}",-101'
+ WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+ WriteRegStr HKCR ".telem" "" "${PROG_ID_TELEM}"
+ WriteRegStr HKCR ".telem" "PerceivedType" "Altus Metrum Telemetry File"
+ WriteRegStr HKCR ".telem" "Content Type" "application/vnd.altusmetrum.telemetry"
+
+ WriteRegStr HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}" ""
+ WriteRegStr HKCR ".telem\${PROG_ID_TELEM}" "" "${REG_NAME}"
+
+ Call RefreshShellIcons
+SectionEnd
+
Section "Uninstaller"
; Deal with the uninstaller
+ ${DisableX64FSRedirection}
SetOutPath $INSTDIR
; Write the install path to the registry
- WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR"
+ WriteRegStr HKLM "SOFTWARE\${REG_NAME}" "Install_Dir" "$INSTDIR"
; Write the uninstall keys for windows
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"'
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "DisplayName" "${REG_NAME}"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "UninstallString" '"$INSTDIR\uninstall-${REG_NAME}.exe"'
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoModify" "1"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoRepair" "1"
- WriteUninstaller "uninstall.exe"
+ WriteUninstaller "uninstall-${REG_NAME}.exe"
SectionEnd
Section "Uninstall"
- DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
- DeleteRegKey HKLM "Software\AltusMetrum"
- Delete "$INSTDIR\*.*"
- RMDir "$INSTDIR"
+ ${DisableX64FSRedirection}
- ; Remove devices
- InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
- InstDrv::DeleteOemInfFiles /NOUNLOAD
- InstDrv::RemoveAllDevices
+ DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}"
+ DeleteRegKey HKLM "SOFTWARE\${REG_NAME}"
+
+ DetailPrint "Delete uninstall reg entries"
+
+ DeleteRegKey HKCR "${PROG_ID_EEPROM}"
+ DeleteRegKey HKCR "${PROG_ID_TELEM}"
+
+ DeleteRegKey HKCR ".eeprom\${PROG_ID_EEPROM}"
+ DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
+
+ DeleteRegKey HKCR ".telem\${PROG_ID_TELEM}"
+ DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}"
+
+ DetailPrint "Delete file association reg entries"
+
+ Delete "$INSTDIR\${FAT_NAME}"
+ Delete "$INSTDIR\uninstall-${REG_NAME}.exe"
+
+ Delete "$INSTDIR\${WIN_APP_ICON}"
+ Delete "$INSTDIR\${WIN_APP_EXE}"
; Remove shortcuts, if any
- Delete "$SMPROGRAMS\AltusMetrum.lnk"
- Delete "$DESKTOP\AltusMetrum.lnk"
+ Delete "$SMPROGRAMS\${REG_NAME}.lnk"
+ Delete "$DESKTOP\${REG_NAME}.lnk"
+ Call un.RefreshShellIcons
SectionEnd
+++ /dev/null
-[Desktop Entry]
-Type=Application
-Name=AltOS UI
-GenericName=Altus Metrum Ground Station
-Comment=View and log downlink data from Altus Metrum products
-Icon=%icondir%/altusmetrum.svg
-Exec=%bindir%/altosui %f
-Terminal=false
-MimeType=text/plain;
-Categories=Education;Electronics;Science;
--- /dev/null
+[Desktop Entry]
+Type=Application
+Version=1.0
+Name=AltOS UI
+GenericName=Altus Metrum Ground Station
+Comment=View and log downlink data from Altus Metrum products
+Icon=%icondir%/altusmetrum-altosui.svg
+Exec=%bindir%/altosui %f
+Terminal=false
+MimeType=application/vnd.altusmetrum.telemetry;application/vnd.altusmetrum.eeprom
+Categories=Education;Electronics;Science;
#
# Create the .desktop file by editing the paths
#
+
case "$target" in
/*)
target_abs="$target"
done
#
-# Figure out where to install the .desktop files. If we can, write it
-# to the public /usr/share/applications, otherwise, write it to the
-# per-user ~/.local/share/applications
+# Install the .desktop file
#
-public=/usr/share/applications
-private=$HOME/.local/share/applications
-apps=""
+for desktop in "$target"/AltOS/*.desktop; do
+ case `id -u` in
+ 0)
+ xdg-desktop-menu install --mode system "$desktop"
+ ;;
+ *)
+ xdg-desktop-menu install --mode user "$desktop"
+ ;;
+ esac
+done
-if [ -d "$public" -a -w "$public" ]; then
- apps="$public"
-else
- mkdir -p "$private" >/dev/null 2>&1
- if [ -d "$private" -a -w "$private" ]; then
- apps="$private"
- fi
-fi
-
-case "$apps" in
-"")
- echo "Cannot install application icon"
- finish 1
- ;;
-esac
+#
+# Install mime type file
+#
+
+for mimetype in "$target"/AltOS/*-mimetypes.xml; do
+ case `id -u` in
+ 0)
+ xdg-mime install --mode system "$mimetype"
+ ;;
+ *)
+ xdg-mime install --mode user "$mimetype"
+ ;;
+ esac
+done
-echo -n "Installing .desktop files to $apps..."
+#
+# Install icons
+#
-cp "$target"/AltOS/*.desktop "$apps"
+for icon_dir in /usr/share/icons/hicolor/scalable/mimetypes "$HOME/.icons" "$HOME/.kde/share/icons"; do
+ if [ -w "$icon_dir" ]; then
+ cp "$target"/AltOS/*.svg "$icon_dir"
+ update-icon-caches "$icon_dir"
+ fi
+done
-case "$?" in
-0)
- echo " done."
- ;;
-*)
- echo " failed."
- ;;
-esac
#
# Install icon to desktop if desired
esac
done
- echo -n "Installing desktop icons..."
case "$do_desktop" in
- [yY]*)
- for d in "$target"/AltOS/*.desktop; do
- ln -f -s "$d" "$HOME/Desktop/"
- done
- ;;
+ [yY]*)
+ echo -n "Installing desktop icons..."
+ for d in "$target"/AltOS/*.desktop; do
+ base=`basename $d`
+ cp --remove-destination "$d" "$HOME/Desktop/"
+ done
+ ;;
esac
echo " done."
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosBTDevice extends altos_bt_device implements AltosDevice {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
AltosBTDevice current;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosBTKnown implements Iterable<AltosBTDevice> {
LinkedList<AltosBTDevice> devices = new LinkedList<AltosBTDevice>();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.basic.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {
LinkedBlockingQueue<AltosBTDevice> found_devices;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosCSVUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
Frame frame;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosDataChooser extends JFileChooser {
JFrame frame;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import libaltosJNI.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import javax.swing.*;
import java.awt.*;
buttonPane.add(cancel_button);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
- add_bluetooth();
+ if (AltosUILib.has_bluetooth)
+ add_bluetooth();
buttonPane.add(select_button);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import javax.swing.*;
import java.awt.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosDisplayThread extends Thread {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosEepromDelete implements Runnable {
AltosEepromList flights;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosEepromManage implements ActionListener {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
JFrame owner;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
class AltosEepromItem implements ActionListener {
AltosEepromLog log;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosFlashUI
extends AltosUIDialog
new AltosHexfileFilter(AltosLib.product_teledongle, "teledongle", "TeleDongle Image"),
new AltosHexfileFilter(AltosLib.product_telemega, "telemega", "TeleMega Image"),
new AltosHexfileFilter(AltosLib.product_easymini, "easymini", "EasyMini Image"),
+ new AltosHexfileFilter(AltosLib.product_easymega, "easymega", "EasyMega Image"),
};
boolean select_source_file() {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
void reset();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import javax.swing.table.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public interface AltosFontListener {
void font_size_changed(int font_size);
+++ /dev/null
-/*
- * 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.
- */
-
-package org.altusmetrum.altosuilib_2;
-
-import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-
-public class AltosFreqList extends JComboBox<AltosFrequency> {
-
- String product;
- int serial;
- int calibrate;
-
- public void set_frequency(double new_frequency) {
- int i;
-
- if (new_frequency < 0) {
- setVisible(false);
- return;
- }
-
- for (i = 0; i < getItemCount(); i++) {
- AltosFrequency f = (AltosFrequency) getItemAt(i);
-
- if (f.close(new_frequency)) {
- setSelectedIndex(i);
- return;
- }
- }
- for (i = 0; i < getItemCount(); i++) {
- AltosFrequency f = (AltosFrequency) getItemAt(i);
-
- if (new_frequency < f.frequency)
- break;
- }
- String description = String.format("%s serial %d", product, serial);
- AltosFrequency frequency = new AltosFrequency(new_frequency, description);
- AltosUIPreferences.add_common_frequency(frequency);
- insertItemAt(frequency, i);
- setMaximumRowCount(getItemCount());
- }
-
- public void set_product(String new_product) {
- product = new_product;
- }
-
- public void set_serial(int new_serial) {
- serial = new_serial;
- }
-
- public double frequency() {
- AltosFrequency f = (AltosFrequency) getSelectedItem();
- if (f != null)
- return f.frequency;
- return 434.550;
- }
-
- public AltosFreqList () {
- super(AltosUIPreferences.common_frequencies());
- setMaximumRowCount(getItemCount());
- setEditable(false);
- product = "Unknown";
- serial = 0;
- }
-
- public AltosFreqList(double in_frequency) {
- this();
- set_frequency(in_frequency);
- }
-}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
}
}
+class AltosDopUnits extends AltosUnits {
+
+ public double value(double p, boolean imperial_units) {
+ return p;
+ }
+
+ public double inverse(double p, boolean imperial_units) {
+ return p;
+ }
+
+ public String show_units(boolean imperial_units) {
+ return null;
+ }
+
+ public String say_units(boolean imperial_units) {
+ return null;
+ }
+
+ public int show_fraction(int width, boolean imperial_units) {
+ return 1;
+ }
+}
+
public class AltosGraph extends AltosUIGraph {
static final private Color height_color = new Color(194,31,31);
static final private Color gps_course_color = new Color (100, 31, 112);
static final private Color gps_ground_speed_color = new Color (31, 112, 100);
static final private Color gps_climb_rate_color = new Color (31, 31, 112);
+ static final private Color gps_pdop_color = new Color(50, 194, 0);
+ static final private Color gps_hdop_color = new Color(50, 0, 194);
+ static final private Color gps_vdop_color = new Color(194, 0, 50);
static final private Color temperature_color = new Color (31, 194, 194);
static final private Color dbm_color = new Color(31, 100, 100);
static final private Color state_color = new Color(0,0,0);
static AltosGyroUnits gyro_units = new AltosGyroUnits();
static AltosOrient orient_units = new AltosOrient();
static AltosMagUnits mag_units = new AltosMagUnits();
+ static AltosDopUnits dop_units = new AltosDopUnits();
AltosUIAxis height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis;
AltosUIAxis distance_axis, pressure_axis;
AltosUIAxis gyro_axis, orient_axis, mag_axis;
- AltosUIAxis course_axis;
+ AltosUIAxis course_axis, dop_axis;
public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosGraphDataSet dataSet) {
super(enable);
orient_axis = newAxis("Tilt Angle", orient_units, orient_color, 0);
mag_axis = newAxis("Magnetic Field", mag_units, mag_x_color, 0);
course_axis = newAxis("Course", orient_units, gps_course_color, 0);
+ dop_axis = newAxis("Dilution of Precision", dop_units, gps_pdop_color, 0);
addMarker("State", AltosGraphDataPoint.data_state, state_color);
gps_climb_rate_color,
enable_gps,
speed_axis);
+ addSeries("GPS Position DOP",
+ AltosGraphDataPoint.data_gps_pdop,
+ dop_units,
+ gps_pdop_color,
+ false,
+ dop_axis);
+ addSeries("GPS Horizontal DOP",
+ AltosGraphDataPoint.data_gps_hdop,
+ dop_units,
+ gps_hdop_color,
+ false,
+ dop_axis);
+ addSeries("GPS Vertical DOP",
+ AltosGraphDataPoint.data_gps_vdop,
+ dop_units,
+ gps_vdop_color,
+ false,
+ dop_axis);
}
if (stats.has_rssi)
addSeries("Received Signal Strength",
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosGraphDataPoint implements AltosUIDataPoint {
public static final int data_gps_course = 27;
public static final int data_gps_ground_speed = 28;
public static final int data_gps_climb_rate = 29;
- public static final int data_ignitor_0 = 30;
+ public static final int data_gps_pdop = 30;
+ public static final int data_gps_hdop = 31;
+ public static final int data_gps_vdop = 32;
+ public static final int data_ignitor_0 = 33;
public static final int data_ignitor_num = 32;
public static final int data_ignitor_max = data_ignitor_0 + data_ignitor_num - 1;
public static final int data_ignitor_fired_0 = data_ignitor_0 + data_ignitor_num;
else
y = AltosLib.MISSING;
break;
+ case data_gps_pdop:
+ if (state.gps != null)
+ y = state.gps.pdop;
+ else
+ y = AltosLib.MISSING;
+ break;
+ case data_gps_hdop:
+ if (state.gps != null)
+ y = state.gps.hdop;
+ else
+ y = AltosLib.MISSING;
+ break;
+ case data_gps_vdop:
+ if (state.gps != null)
+ y = state.gps.vdop;
+ else
+ y = AltosLib.MISSING;
+ break;
default:
if (data_ignitor_0 <= index && index <= data_ignitor_max) {
int ignitor = index - data_ignitor_0;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
AltosGraphDataSet dataSet;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
private AltosFlightInfoTableModel model;
if (state.gps_height != AltosLib.MISSING)
info_add_row(1, "GPS height", "%8.1f", state.gps_height);
- /* The SkyTraq GPS doesn't report these values */
- /*
- if (false) {
- info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°",
- state.gps.ground_speed,
- state.gps.course);
- info_add_row(1, "GPS climb rate", "%8.1f m/s",
- state.gps.climb_rate);
- info_add_row(1, "GPS error", "%6d m(h)%3d m(v)",
- state.gps.h_error, state.gps.v_error);
- }
- */
-
- info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop);
+ if (state.gps.ground_speed != AltosLib.MISSING && state.gps.course != AltosLib.MISSING)
+ info_add_row(1, "GPS ground speed", "%6.1f m/s %3d°",
+ state.gps.ground_speed,
+ state.gps.course);
+ if (state.gps.climb_rate != AltosLib.MISSING)
+ info_add_row(1, "GPS climb rate", "%6.1f m/s",
+ state.gps.climb_rate);
+
+ if (state.gps.h_error != AltosLib.MISSING && state.gps.v_error != AltosLib.MISSING)
+ info_add_row(1, "GPS error", "%6d m(h)%3d m(v)",
+ state.gps.h_error, state.gps.v_error);
+ if (state.gps.pdop != AltosLib.MISSING &&
+ state.gps.hdop != AltosLib.MISSING &&
+ state.gps.vdop != AltosLib.MISSING)
+ info_add_row(1, "GPS dop", "%3.1fp/%3.1fh/%3.1fv",
+ state.gps.pdop,
+ state.gps.hdop,
+ state.gps.vdop);
if (state.npad > 0) {
if (state.from_pad != null) {
- info_add_row(1, "Distance from pad", "%6d m",
+ info_add_row(1, "Ground pad dist", "%6d m",
(int) (state.from_pad.distance + 0.5));
info_add_row(1, "Direction from pad", "%6d°",
(int) (state.from_pad.bearing + 0.5));
info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt);
}
if (state.gps.year != AltosLib.MISSING)
- info_add_row(1, "GPS date", "%04d-%02d-%02d",
+ info_add_row(2, "GPS date", "%04d-%02d-%02d",
state.gps.year,
state.gps.month,
state.gps.day);
if (state.gps.hour != AltosLib.MISSING)
- info_add_row(1, "GPS time", " %02d:%02d:%02d",
+ info_add_row(2, "GPS time", " %02d:%02d:%02d",
state.gps.hour,
state.gps.minute,
state.gps.second);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import javax.swing.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import javax.swing.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public interface AltosPositionListener {
public void position_changed(int position);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosRomconfigUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
class AltosScanResult {
String callsign;
int flight;
AltosFrequency frequency;
int telemetry;
+ int rate;
boolean interrupted = false;
public String toString() {
- return String.format("%-9.9s serial %-4d flight %-4d (%s %s)",
- callsign, serial, flight, frequency.toShortString(), AltosLib.telemetry_name(telemetry));
+ return String.format("%-9.9s serial %-4d flight %-4d (%s %s %d)",
+ callsign, serial, flight,
+ frequency.toShortString(),
+ AltosLib.telemetry_name(telemetry),
+ AltosLib.ao_telemetry_rate_values[rate]);
}
public String toShortString() {
- return String.format("%s %d %d %7.3f %d",
- callsign, serial, flight, frequency, telemetry);
+ return String.format("%s %d %d %7.3f %d %d",
+ callsign, serial, flight, frequency, telemetry, rate);
}
public AltosScanResult(String in_callsign, int in_serial,
- int in_flight, AltosFrequency in_frequency, int in_telemetry) {
+ int in_flight, AltosFrequency in_frequency,
+ int in_telemetry,
+ int in_rate) {
callsign = in_callsign;
serial = in_serial;
flight = in_flight;
frequency = in_frequency;
telemetry = in_telemetry;
+ rate = in_rate;
}
public boolean equals(AltosScanResult other) {
return (serial == other.serial &&
frequency.frequency == other.frequency.frequency &&
- telemetry == other.telemetry);
+ telemetry == other.telemetry &&
+ rate == other.rate);
}
public boolean up_to_date(AltosScanResult other) {
private JLabel scanning_label;
private JLabel frequency_label;
private JLabel telemetry_label;
+ private JLabel rate_label;
private JButton cancel_button;
private JButton monitor_button;
private JCheckBox[] telemetry_boxes;
+ private JCheckBox[] rate_boxes;
javax.swing.Timer timer;
AltosScanResults results = new AltosScanResults();
int telemetry;
boolean select_telemetry = false;
+ int rate;
+ boolean select_rate = false;
+
final static int timeout = 1200;
TelemetryHandler handler;
Thread thread;
continue;
if (state.flight != AltosLib.MISSING) {
final AltosScanResult result = new AltosScanResult(state.callsign,
- state.serial,
- state.flight,
- frequencies[frequency_index],
- telemetry);
+ state.serial,
+ state.flight,
+ frequencies[frequency_index],
+ telemetry,
+ rate);
Runnable r = new Runnable() {
public void run() {
results.add(result);
frequency_label.setText(String.format("Frequency: %s", frequencies[frequency_index].toString()));
if (select_telemetry)
telemetry_label.setText(String.format("Telemetry: %s", AltosLib.telemetry_name(telemetry)));
+ if (select_rate)
+ rate_label.setText(String.format("Rate: %d baud", AltosLib.ao_telemetry_rate_values[rate]));
}
void set_telemetry() {
reader.set_telemetry(telemetry);
}
+ void set_rate() {
+ reader.set_telemetry_rate(rate);
+ }
+
void set_frequency() throws InterruptedException, TimeoutException {
reader.set_frequency(frequencies[frequency_index].frequency);
reader.reset();
void next() throws InterruptedException, TimeoutException {
reader.set_monitor(false);
+
+ /* Let any pending input from the last configuration drain out */
Thread.sleep(100);
- ++frequency_index;
+
+ if (select_rate) {
+ boolean wrapped = false;
+ do {
+ ++rate;
+ if (rate > AltosLib.ao_telemetry_rate_max) {
+ wrapped = true;
+ rate = 0;
+ }
+ } while (!rate_boxes[rate].isSelected());
+ set_rate();
+ if (!wrapped) {
+ set_label();
+ return;
+ }
+ }
if (select_telemetry) {
- if (frequency_index >= frequencies.length ||
- !telemetry_boxes[telemetry - AltosLib.ao_telemetry_min].isSelected())
- {
- frequency_index = 0;
- do {
- ++telemetry;
- if (telemetry > AltosLib.ao_telemetry_max)
- telemetry = AltosLib.ao_telemetry_min;
- } while (!telemetry_boxes[telemetry - AltosLib.ao_telemetry_min].isSelected());
- set_telemetry();
+ boolean wrapped = false;
+ do {
+ ++telemetry;
+ if (telemetry > AltosLib.ao_telemetry_max) {
+ wrapped = true;
+ telemetry = AltosLib.ao_telemetry_min;
+ }
+ } while (!telemetry_boxes[telemetry - AltosLib.ao_telemetry_min].isSelected());
+ set_telemetry();
+ if (!wrapped) {
+ set_label();
+ return;
}
- } else {
- if (frequency_index >= frequencies.length)
- frequency_index = 0;
}
+ ++frequency_index;
+ if (frequency_index >= frequencies.length)
+ frequency_index = 0;
set_frequency();
set_label();
reader.set_monitor(true);
AltosUIPreferences.set_scanning_telemetry(scanning_telemetry);
}
+ if (cmd.equals("rate")) {
+ int k;
+ int scanning_rate = 0;
+ for (k = 0; k <= AltosLib.ao_telemetry_rate_max; k++) {
+ if (rate_boxes[k].isSelected())
+ scanning_rate |= (1 << k);
+ }
+ if (scanning_rate == 0) {
+ scanning_rate = (1 << 0);
+ rate_boxes[0].setSelected(true);
+ }
+ AltosUIPreferences.set_scanning_telemetry_rate(scanning_rate);
+ }
+
if (cmd.equals("monitor")) {
close();
AltosScanResult r = (AltosScanResult) (list.getSelectedValue());
if (r != null) {
if (device != null) {
if (reader != null) {
+ System.out.printf("frequency %g rate %d\n", r.frequency.frequency, r.rate);
reader.set_telemetry(r.telemetry);
+ reader.set_telemetry_rate(r.rate);
reader.set_frequency(r.frequency.frequency);
reader.save_frequency();
+ reader.save_telemetry();
+ reader.save_telemetry_rate();
owner.scan_device_selected(device);
}
}
reader = new AltosTelemetryReader(new AltosSerial(device));
set_frequency();
set_telemetry();
+ set_rate();
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
owner = in_owner;
select_telemetry = in_select_telemetry;
+ select_rate = true;
frequencies = AltosUIPreferences.common_frequencies();
frequency_index = 0;
telemetry = AltosLib.ao_telemetry_standard;
+ rate = 0;
if (!open())
return;
if (select_telemetry) {
telemetry_label = new JLabel("");
+ telemetry_label.setPreferredSize(new Dimension(100, 16));
telemetry = AltosLib.ao_telemetry_min;
} else {
telemetry = AltosLib.ao_telemetry_standard;
}
+ if (select_rate) {
+ rate_label = new JLabel("");
+ rate_label.setPreferredSize(new Dimension(100, 16));
+ }
+
set_label();
c.fill = GridBagConstraints.HORIZONTAL;
- c.anchor = GridBagConstraints.WEST;
+ c.anchor = GridBagConstraints.LINE_START;
c.insets = i;
- c.weightx = 1;
- c.weighty = 1;
+ c.weightx = 0;
+ c.weighty = 0;
c.gridx = 0;
c.gridy = 0;
c.gridy = 1;
pane.add(frequency_label, c);
- int y_offset = 3;
+ int y_offset_rate = 3;
+ int y_offset_telem = 3;
+
+ int check_x = 0;
+
+ if (select_rate && select_telemetry)
+ c.gridwidth = 1;
+
+ if (select_rate) {
+ c.gridy = 2;
+ c.gridx = check_x++;
+ pane.add(rate_label, c);
+
+ int scanning_rate = AltosUIPreferences.scanning_telemetry_rate();
+ rate_boxes = new JCheckBox[AltosLib.ao_telemetry_rate_max + 1];
+ for (int k = 0; k <= AltosLib.ao_telemetry_rate_max; k++) {
+ rate_boxes[k] = new JCheckBox(String.format("%d baud", AltosLib.ao_telemetry_rate_values[k]));
+ c.gridy = y_offset_rate + k;
+ pane.add(rate_boxes[k], c);
+ rate_boxes[k].setActionCommand("rate");
+ rate_boxes[k].addActionListener(this);
+ rate_boxes[k].setSelected((scanning_rate & (1 << k)) != 0);
+ }
+ y_offset_rate += AltosLib.ao_telemetry_rate_max + 1;
+ }
if (select_telemetry) {
c.gridy = 2;
+ c.gridx = check_x++;
pane.add(telemetry_label, c);
int scanning_telemetry = AltosUIPreferences.scanning_telemetry();
for (int k = AltosLib.ao_telemetry_min; k <= AltosLib.ao_telemetry_max; k++) {
int j = k - AltosLib.ao_telemetry_min;
telemetry_boxes[j] = new JCheckBox(AltosLib.telemetry_name(k));
- c.gridy = 3 + j;
+ c.gridy = y_offset_telem + j;
pane.add(telemetry_boxes[j], c);
telemetry_boxes[j].setActionCommand("telemetry");
telemetry_boxes[j].addActionListener(this);
telemetry_boxes[j].setSelected((scanning_telemetry & (1 << k)) != 0);
}
- y_offset += (AltosLib.ao_telemetry_max - AltosLib.ao_telemetry_min + 1);
+ y_offset_telem += (AltosLib.ao_telemetry_max - AltosLib.ao_telemetry_min + 1);
}
+ int y_offset = Math.max(y_offset_rate, y_offset_telem);
+
list = new JList<AltosScanResult>(results) {
//Subclass JList to workaround bug 4832765, which can cause the
//scroll pane to not let the user easily scroll up to the beginning
* Deal with TeleDongle on a serial port
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import libaltosJNI.*;
/*
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public class AltosSerialInUseException extends Exception {
public AltosDevice device;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
public final static int axis_default = axis_include_zero;
public void set_units() {
- setLabel(String.format("%s (%s)", label, units.show_units()));
+ String u = units.show_units();
+ if (u != null)
+ setLabel(String.format("%s (%s)", label, u));
+ else
+ setLabel(label);
}
public void set_enable(boolean enable) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
row++;
}
+ static final Integer map_caches[] = { 9, 25, 100 };
+
+ public void add_map_cache() {
+ pane.add(new JLabel("Map Cache Size"), constraints(0, 1));
+
+ final JComboBox<Integer> map_cache = new JComboBox<Integer>(map_caches);
+
+ map_cache.setEditable(true);
+ map_cache.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ int size = (Integer) (map_cache.getSelectedItem());
+
+ AltosUIPreferences.set_map_cache(size);
+ } catch (ClassCastException ce) {
+ map_cache.setSelectedItem(new Integer(AltosUIPreferences.map_cache()));
+ }
+ }
+ });
+
+ map_cache.setSelectedItem (new Integer(AltosUIPreferences.map_cache()));
+ pane.add(map_cache, constraints(1, 2, GridBagConstraints.BOTH));
+ row++;
+ }
+
public void add_bluetooth() {
}
add_font_size();
add_look_and_feel();
add_position();
- add_bluetooth();
+ add_map_cache();
+ if (AltosUILib.has_bluetooth)
+ add_bluetooth();
add_frequencies();
/* And a close button at the bottom */
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public class AltosUIDataMissing extends Exception {
public int id;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public interface AltosUIDataPoint {
public abstract double x() throws AltosUIDataMissing;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public interface AltosUIDataSet {
public abstract String name();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {
public GridBagLayout layout;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
}
static String[] altos_icon_names = {
- "/altus-metrum-16.png",
- "/altus-metrum-32.png",
- "/altus-metrum-48.png",
- "/altus-metrum-64.png",
- "/altus-metrum-128.png",
- "/altus-metrum-256.png"
+ "/altusmetrum-altosui-16.png",
+ "/altusmetrum-altosui-32.png",
+ "/altusmetrum-altosui-48.png",
+ "/altusmetrum-altosui-64.png",
+ "/altusmetrum-altosui-128.png",
+ "/altusmetrum-altosui-256.png"
};
static public String[] icon_names;
}
}
+ static boolean global_settings_done;
+
+ public String getName() {
+ return "Altus Metrum";
+ }
+
+ public void macosx_quit_handler() {
+ System.out.printf("Got quit handler\n");
+ }
+
+ public void macosx_about_handler() {
+ System.out.printf("Got about handler\n");
+ }
+
+ public void macosx_preferences_handler() {
+ System.out.printf("Got preferences handler\n");
+ }
+
+ public void macosx_file_handler(String path) {
+ System.out.printf("Got file handler with \"%s\"\n", path);
+ }
+
+ /* Check that we are on Mac OS X. This is crucial to loading and using the OSXAdapter class.
+ */
+ public static boolean MAC_OS_X = (System.getProperty("os.name").toLowerCase().startsWith("mac os x"));
+
+ private static boolean registered_for_macosx_events;
+
+ /* Generic registration with the Mac OS X application menu
+ * Checks the platform, then attempts to register with the Apple EAWT
+ * See OSXAdapter.java to see how this is done without directly referencing any Apple APIs
+ */
+ public synchronized void register_for_macosx_events() {
+ if (registered_for_macosx_events)
+ return;
+ registered_for_macosx_events = true;
+ if (MAC_OS_X) {
+ try {
+ // Generate and register the OSXAdapter, passing it a hash of all the methods we wish to
+ // use as delegates for various com.apple.eawt.ApplicationListener methods
+ OSXAdapter.setQuitHandler(this, getClass().getDeclaredMethod("macosx_quit_handler", (Class[])null));
+// OSXAdapter.setAboutHandler(this, getClass().getDeclaredMethod("macosx_about_handler", (Class[])null));
+ OSXAdapter.setPreferencesHandler(this, getClass().getDeclaredMethod("macosx_preferences_handler", (Class[])null));
+ OSXAdapter.setFileHandler(this, getClass().getDeclaredMethod("macosx_file_handler", new Class[] { String.class }));
+ } catch (Exception e) {
+ System.err.println("Error while loading the OSXAdapter:");
+ e.printStackTrace();
+ }
+ }
+ }
void init() {
AltosUIPreferences.register_ui_listener(this);
AltosUIPreferences.register_position_listener(this);
position = AltosUIPreferences.position();
addWindowListener(new AltosUIFrameListener());
+
+ /* Try to make menus live in the menu bar like regular Mac apps */
+ if (!global_settings_done) {
+ try {
+ global_settings_done = true;
+ System.setProperty("com.apple.mrj.application.apple.menu.about.name", getName());
+ System.setProperty("com.apple.macos.useScreenMenuBar", "true");
+ System.setProperty("apple.laf.useScreenMenuBar", "true" ); // for older versions of Java
+ } catch (Exception e) {
+ }
+ }
set_icon();
}
--- /dev/null
+/*
+ * 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.
+ */
+
+package org.altusmetrum.altosuilib_3;
+
+import javax.swing.*;
+import org.altusmetrum.altoslib_5.*;
+
+public class AltosUIFreqList extends JComboBox<AltosFrequency> {
+
+ String product;
+ int serial;
+ int calibrate;
+
+ public void set_frequency(double new_frequency) {
+ int i;
+
+ if (new_frequency < 0) {
+ setVisible(false);
+ return;
+ }
+
+ for (i = 0; i < getItemCount(); i++) {
+ AltosFrequency f = (AltosFrequency) getItemAt(i);
+
+ if (f.close(new_frequency)) {
+ setSelectedIndex(i);
+ return;
+ }
+ }
+ for (i = 0; i < getItemCount(); i++) {
+ AltosFrequency f = (AltosFrequency) getItemAt(i);
+
+ if (new_frequency < f.frequency)
+ break;
+ }
+ String description = String.format("%s serial %d", product, serial);
+ AltosFrequency frequency = new AltosFrequency(new_frequency, description);
+ AltosUIPreferences.add_common_frequency(frequency);
+ insertItemAt(frequency, i);
+ setMaximumRowCount(getItemCount());
+ setVisible(true);
+ }
+
+ public void set_product(String new_product) {
+ product = new_product;
+ }
+
+ public void set_serial(int new_serial) {
+ serial = new_serial;
+ }
+
+ public double frequency() {
+ AltosFrequency f = (AltosFrequency) getSelectedItem();
+ if (f != null)
+ return f.frequency;
+ return 434.550;
+ }
+
+ public AltosUIFreqList () {
+ super(AltosUIPreferences.common_frequencies());
+ setMaximumRowCount(getItemCount());
+ setEditable(false);
+ product = "Unknown";
+ serial = 0;
+ }
+
+ public AltosUIFreqList(double in_frequency) {
+ this();
+ set_frequency(in_frequency);
+ }
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
JLabel label;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUILatLon {
public double lat;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUILib extends AltosLib {
static public boolean initialized = false;
static public boolean loaded_library = false;
+ static public boolean has_bluetooth = false;
static final String[] library_names = { "altos", "altos32", "altos64" };
loaded_library = false;
}
}
+
+ String OS = System.getProperty("os.name");
+
+ if (OS.startsWith("Linux")) {
+ has_bluetooth = true;
+ }
+
initialized = true;
}
return loaded_library;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public interface AltosUIListener {
public void ui_changed(String look_and_feel);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosUIMapZoomListener {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.io.*;
import java.net.*;
-public class AltosUIMapCache {
+public class AltosUIMapCache implements AltosUIMapCacheListener {
static final int success = 0;
static final int loading = 1;
static final int failed = 2;
static final int bad_request = 3;
static final int forbidden = 4;
- static final int min_cache_size = 9;
- static final int max_cache_size = 24;
+ int min_cache_size; /* configured minimum cache size */
+ int cache_size; /* current cache size */
+ int requested_cache_size; /* cache size computed by application */
private Object fetch_lock = new Object();
private Object cache_lock = new Object();
- int cache_size = min_cache_size;
-
AltosUIMapImage[] images = new AltosUIMapImage[cache_size];
long used;
public void set_cache_size(int new_size) {
+
+ requested_cache_size = new_size;
+
if (new_size < min_cache_size)
new_size = min_cache_size;
- if (new_size > max_cache_size)
- new_size = max_cache_size;
+
if (new_size == cache_size)
return;
}
}
+ public void map_cache_changed(int map_cache) {
+ min_cache_size = map_cache;
+
+ set_cache_size(requested_cache_size);
+ }
+
+ public void dispose() {
+ AltosUIPreferences.unregister_map_cache_listener(this);
+
+ for (int i = 0; i < cache_size; i++) {
+ AltosUIMapImage image = images[i];
+
+ if (image != null)
+ image.flush();
+ }
+ }
+
public AltosUIMapCache() {
+ min_cache_size = AltosUIPreferences.map_cache();
+
+ set_cache_size(0);
+
+ AltosUIPreferences.register_map_cache_listener(this);
}
}
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib_3;
+
+public interface AltosUIMapCacheListener {
+ public void map_cache_changed(int map_cache);
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import javax.swing.*;
import javax.imageio.ImageIO;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUIMapLine {
AltosUILatLon start, end;
private Font font = null;
+ static public int stroke_width = 6;
public void set_font(Font font) {
this.font = font;
}
public void paint(Graphics2D g, AltosUIMapTransform t) {
- g.setColor(Color.BLUE);
if (start == null || end == null)
return;
+ g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
Line2D.Double line = new Line2D.Double(t.screen(start),
t.screen(end));
+ g.setColor(Color.WHITE);
+ g.setStroke(new BasicStroke(stroke_width+4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+ g.draw(line);
+
+ g.setColor(Color.BLUE);
+ g.setStroke(new BasicStroke(stroke_width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g.draw(line);
String message = line_dist();
- g.setFont(font);
- g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Rectangle2D bounds;
bounds = font.getStringBounds(message, g.getFontRenderContext());
} else {
x += 2.0f;
}
+
+ g.setFont(font);
+ g.setColor(Color.WHITE);
+ for (int dy = -2; dy <= 2; dy += 2)
+ for (int dx = -2; dx <= 2; dx += 2)
+ g.drawString(message, x + dx, y + dy);
+ g.setColor(Color.BLUE);
g.drawString(message, x, y);
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUIMapMark {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
class PathPoint {
AltosUILatLon lat_lon;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import java.net.URL;
import java.net.URLConnection;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
class AltosUIMapPos extends Box {
AltosUIFrame owner;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public class AltosUIMapRectangle {
AltosUILatLon ul, lr;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.net.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public interface AltosUIMapStoreListener {
abstract void notify_store(AltosUIMapStore store, int status);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import java.awt.RenderingHints.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUIMapTile {
AltosUIMapTileListener listener;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public interface AltosUIMapTileListener {
abstract public void notify_tile(AltosUIMapTile tile, int status);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUIMapTransform {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUIMapView extends Component implements MouseMotionListener, MouseListener, MouseWheelListener, ComponentListener, AltosUIMapTileListener, AltosUIMapStoreListener {
AltosUILatLon centre;
public void set_font() {
- line.set_font(AltosUILib.value_font);
+ line.set_font(AltosUILib.status_font);
for (AltosUIMapTile tile : tiles.values())
tile.set_font(AltosUILib.value_font);
repaint();
for (Point point : to_remove)
tiles.remove(point);
- cache.set_cache_size(((lower_right.y - upper_left.y) / px_size + 1) * ((lower_right.x - upper_left.x) / px_size + 1));
+ cache.set_cache_size((getWidth() / px_size + 2) * (getHeight() / px_size + 2));
for (int y = upper_left.y; y <= lower_right.y; y += px_size) {
for (int x = upper_left.x; x <= lower_right.x; x += px_size) {
Point point = new Point(x, y);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public interface AltosUIMapZoomListener {
abstract public void zoom_changed(int zoom);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.util.*;
import java.awt.Component;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class AltosUIPreferences extends AltosPreferences {
/* Window position preference name */
final static String positionPreference = "POSITION";
+ /* Maps cache size preference name */
+ final static String mapCachePreference = "MAP-CACHE";
+
/* UI Component to pop dialogs up */
static Component component;
public static int position = AltosUILib.position_top_left;
+ static LinkedList<AltosUIMapCacheListener> map_cache_listeners;
+
+ public static int map_cache = 9;
+
public static void init() {
AltosPreferences.init(new AltosUIPreferencesBackend());
position = backend.getInt(positionPreference, AltosUILib.position_top_left);
position_listeners = new LinkedList<AltosPositionListener>();
+
+ map_cache = backend.getInt(mapCachePreference, 9);
+ map_cache_listeners = new LinkedList<AltosUIMapCacheListener>();
}
static { init(); }
return position;
}
}
+
+ public static void register_map_cache_listener(AltosUIMapCacheListener l) {
+ synchronized(backend) {
+ map_cache_listeners.add(l);
+ }
+ }
+
+ public static void unregister_map_cache_listener(AltosUIMapCacheListener l) {
+ synchronized (backend) {
+ map_cache_listeners.remove(l);
+ }
+ }
+
+ public static void set_map_cache(int new_map_cache) {
+ synchronized(backend) {
+ map_cache = new_map_cache;
+ backend.putInt(mapCachePreference, map_cache);
+ flush_preferences();
+ for (AltosUIMapCacheListener l: map_cache_listeners)
+ l.map_cache_changed(map_cache);
+ }
+ }
+
+ public static int map_cache() {
+ synchronized(backend) {
+ return map_cache;
+ }
+ }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.File;
import java.util.prefs.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import javax.swing.filechooser.FileSystemView;
public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
--- /dev/null
+/*
+ * 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.
+ */
+
+package org.altusmetrum.altosuilib_3;
+
+import javax.swing.*;
+import org.altusmetrum.altoslib_5.*;
+
+public class AltosUIRateList extends JComboBox<String> {
+
+ String product;
+ int serial;
+
+ public void set_rate(int new_rate) {
+ int i;
+
+ setVisible(new_rate >= 0);
+ setSelectedIndex(new_rate);
+ }
+
+ public void set_product(String new_product) {
+ product = new_product;
+ }
+
+ public void set_serial(int new_serial) {
+ serial = new_serial;
+ }
+
+ public int rate() {
+ return getSelectedIndex();
+ }
+
+ public AltosUIRateList () {
+ super();
+ for (int i = 0; i < AltosLib.ao_telemetry_rate_values.length; i++)
+ addItem(String.format("%d baud", AltosLib.ao_telemetry_rate_values[i]));
+ setMaximumRowCount(getItemCount());
+ setEditable(false);
+ product = "Unknown";
+ serial = 0;
+ }
+
+ public AltosUIRateList(int in_rate) {
+ this();
+ set_rate(in_rate);
+ }
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altosuilib_3;
+
+import java.util.*;
+import javax.swing.*;
+import org.altusmetrum.altoslib_5.*;
+
+
+public class AltosUITelemetryList extends JComboBox<String> {
+ public int get_selected() {
+ return getSelectedIndex() + 1;
+ }
+
+ public void set_selected(int telemetry) {
+ setSelectedIndex(telemetry-1);
+ }
+
+ public AltosUITelemetryList(int serial) {
+ super();
+ for (int i = AltosLib.ao_telemetry_min; i <= AltosLib.ao_telemetry_max; i++)
+ addItem(AltosLib.telemetry_name(i));
+
+ int telemetry = AltosPreferences.telemetry(serial);
+ if (telemetry < AltosLib.ao_telemetry_min || AltosLib.ao_telemetry_max < telemetry)
+ telemetry = AltosLib.ao_telemetry_standard;
+ setMaximumRowCount(AltosLib.ao_telemetry_max);
+ set_selected(telemetry);
+ revalidate();
+ }
+}
+
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
public class AltosUIVersion {
public final static String version = "@VERSION@";
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.util.*;
import libaltosJNI.*;
if (want_product == AltosUILib.product_altimeter)
return have_product == AltosUILib.product_telemetrum ||
have_product == AltosUILib.product_telemega ||
+ have_product == AltosUILib.product_easymega ||
have_product == AltosUILib.product_telegps ||
have_product == AltosUILib.product_easymini ||
have_product == AltosUILib.product_telemini;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.VoiceManager;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_2;
+package org.altusmetrum.altosuilib_3;
import java.awt.*;
import java.awt.event.*;
AltosVoice.java \
AltosDisplayThread.java \
AltosDeviceUIDialog.java \
- AltosFreqList.java \
AltosSerial.java \
AltosSerialInUseException.java \
AltosConfigFreqUI.java \
AltosUIMapPath.java \
AltosUIMapTile.java \
AltosUIMapCache.java \
+ AltosUIMapCacheListener.java \
AltosUIMapImage.java \
AltosUIMapTransform.java \
AltosUIMapRectangle.java \
AltosUIFlightTab.java \
AltosUIIndicator.java \
AltosUIUnitsIndicator.java \
- AltosUIVoltageIndicator.java
+ AltosUIVoltageIndicator.java \
+ AltosUIFreqList.java \
+ AltosUITelemetryList.java \
+ AltosUIRateList.java \
+ OSXAdapter.java
JAR=altosuilib_$(ALTOSUILIB_VERSION).jar
all-local: $(JAR)
clean-local:
- -rm -rf $(JAVAROOT) $(JAR)
+ -rm -rf $(JAVAROOT) altosuilib_*.jar
install-altosuilibJAVA: $(JAR)
@$(NORMAL_INSTALL)
--- /dev/null
+/*
+
+File: OSXAdapter.java
+
+Abstract: Hooks existing preferences/about/quit functionality from an
+ existing Java app into handlers for the Mac OS X application menu.
+ Uses a Proxy object to dynamically implement the
+ com.apple.eawt.ApplicationListener interface and register it with the
+ com.apple.eawt.Application object. This allows the complete project
+ to be both built and run on any platform without any stubs or
+ placeholders. Useful for developers looking to implement Mac OS X
+ features while supporting multiple platforms with minimal impact.
+
+Version: 2.0
+
+Disclaimer: IMPORTANT: This Apple software is supplied to you by
+Apple Inc. ("Apple") in consideration of your agreement to the
+following terms, and your use, installation, modification or
+redistribution of this Apple software constitutes acceptance of these
+terms. If you do not agree with these terms, please do not use,
+install, modify or redistribute this Apple software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, Apple grants you a personal, non-exclusive
+license, under Apple's copyrights in this original Apple software (the
+"Apple Software"), to use, reproduce, modify and redistribute the Apple
+Software, with or without modifications, in source and/or binary forms;
+provided that if you redistribute the Apple Software in its entirety and
+without modifications, you must retain this notice and the following
+text and disclaimers in all such redistributions of the Apple Software.
+Neither the name, trademarks, service marks or logos of Apple Inc.
+may be used to endorse or promote products derived from the Apple
+Software without specific prior written permission from Apple. Except
+as expressly stated in this notice, no other rights or licenses, express
+or implied, are granted by Apple herein, including but not limited to
+any patent rights that may be infringed by your derivative works or by
+other works in which the Apple Software may be incorporated.
+
+The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+Copyright © 2003-2007 Apple, Inc., All Rights Reserved
+
+*/
+
+package org.altusmetrum.altosuilib_3;
+
+import java.lang.reflect.*;
+import java.util.HashMap;
+
+
+public class OSXAdapter implements InvocationHandler {
+
+ protected Object targetObject;
+ protected Method targetMethod;
+ protected String proxySignature;
+
+ static Object macOSXApplication;
+
+ // Pass this method an Object and Method equipped to perform application shutdown logic
+ // The method passed should return a boolean stating whether or not the quit should occur
+ public static void setQuitHandler(Object target, Method quitHandler) {
+ setHandler(new OSXAdapter("handleQuit", target, quitHandler));
+ }
+
+ // Pass this method an Object and Method equipped to display application info
+ // They will be called when the About menu item is selected from the application menu
+ public static void setAboutHandler(Object target, Method aboutHandler) {
+ boolean enableAboutMenu = (target != null && aboutHandler != null);
+ if (enableAboutMenu) {
+ setHandler(new OSXAdapter("handleAbout", target, aboutHandler));
+ }
+ // If we're setting a handler, enable the About menu item by calling
+ // com.apple.eawt.Application reflectively
+ try {
+ Method enableAboutMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledAboutMenu", new Class[] { boolean.class });
+ enableAboutMethod.invoke(macOSXApplication, new Object[] { Boolean.valueOf(enableAboutMenu) });
+ } catch (Exception ex) {
+ System.err.println("OSXAdapter could not access the About Menu");
+ ex.printStackTrace();
+ }
+ }
+
+ // Pass this method an Object and a Method equipped to display application options
+ // They will be called when the Preferences menu item is selected from the application menu
+ public static void setPreferencesHandler(Object target, Method prefsHandler) {
+ boolean enablePrefsMenu = (target != null && prefsHandler != null);
+ if (enablePrefsMenu) {
+ setHandler(new OSXAdapter("handlePreferences", target, prefsHandler));
+ }
+ // If we're setting a handler, enable the Preferences menu item by calling
+ // com.apple.eawt.Application reflectively
+ try {
+ Method enablePrefsMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledPreferencesMenu", new Class[] { boolean.class });
+ enablePrefsMethod.invoke(macOSXApplication, new Object[] { Boolean.valueOf(enablePrefsMenu) });
+ } catch (Exception ex) {
+ System.err.println("OSXAdapter could not access the About Menu");
+ ex.printStackTrace();
+ }
+ }
+
+ // Pass this method an Object and a Method equipped to handle document events from the Finder
+ // Documents are registered with the Finder via the CFBundleDocumentTypes dictionary in the
+ // application bundle's Info.plist
+ public static void setFileHandler(Object target, Method fileHandler) {
+ setHandler(new OSXAdapter("handleOpenFile", target, fileHandler) {
+ // Override OSXAdapter.callTarget to send information on the
+ // file to be opened
+ public boolean callTarget(Object appleEvent) {
+ if (appleEvent != null) {
+ try {
+ Method getFilenameMethod = appleEvent.getClass().getDeclaredMethod("getFilename", (Class[])null);
+ String filename = (String) getFilenameMethod.invoke(appleEvent, (Object[])null);
+ this.targetMethod.invoke(this.targetObject, new Object[] { filename });
+ } catch (Exception ex) {
+
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ // setHandler creates a Proxy object from the passed OSXAdapter and adds it as an ApplicationListener
+ public static void setHandler(OSXAdapter adapter) {
+ try {
+ Class applicationClass = Class.forName("com.apple.eawt.Application");
+ if (macOSXApplication == null) {
+ macOSXApplication = applicationClass.getConstructor((Class[])null).newInstance((Object[])null);
+ }
+ Class applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener");
+ Method addListenerMethod = applicationClass.getDeclaredMethod("addApplicationListener", new Class[] { applicationListenerClass });
+ // Create a proxy object around this handler that can be reflectively added as an Apple ApplicationListener
+ Object osxAdapterProxy = Proxy.newProxyInstance(OSXAdapter.class.getClassLoader(), new Class[] { applicationListenerClass }, adapter);
+ addListenerMethod.invoke(macOSXApplication, new Object[] { osxAdapterProxy });
+ } catch (ClassNotFoundException cnfe) {
+ System.err.println("This version of Mac OS X does not support the Apple EAWT. ApplicationEvent handling has been disabled (" + cnfe + ")");
+ } catch (Exception ex) { // Likely a NoSuchMethodException or an IllegalAccessException loading/invoking eawt.Application methods
+ System.err.println("Mac OS X Adapter could not talk to EAWT:");
+ ex.printStackTrace();
+ }
+ }
+
+ // Each OSXAdapter has the name of the EAWT method it intends to listen for (handleAbout, for example),
+ // the Object that will ultimately perform the task, and the Method to be called on that Object
+ protected OSXAdapter(String proxySignature, Object target, Method handler) {
+ this.proxySignature = proxySignature;
+ this.targetObject = target;
+ this.targetMethod = handler;
+ }
+
+ // Override this method to perform any operations on the event
+ // that comes with the various callbacks
+ // See setFileHandler above for an example
+ public boolean callTarget(Object appleEvent) throws InvocationTargetException, IllegalAccessException {
+ Object result = targetMethod.invoke(targetObject, (Object[])null);
+ if (result == null) {
+ return true;
+ }
+ return Boolean.valueOf(result.toString()).booleanValue();
+ }
+
+ // InvocationHandler implementation
+ // This is the entry point for our proxy object; it is called every time an ApplicationListener method is invoked
+ public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {
+ if (isCorrectMethod(method, args)) {
+ boolean handled = callTarget(args[0]);
+ setApplicationEventHandled(args[0], handled);
+ }
+ // All of the ApplicationListener methods are void; return null regardless of what happens
+ return null;
+ }
+
+ // Compare the method that was called to the intended method when the OSXAdapter instance was created
+ // (e.g. handleAbout, handleQuit, handleOpenFile, etc.)
+ protected boolean isCorrectMethod(Method method, Object[] args) {
+ return (targetMethod != null && proxySignature.equals(method.getName()) && args.length == 1);
+ }
+
+ // It is important to mark the ApplicationEvent as handled and cancel the default behavior
+ // This method checks for a boolean result from the proxy method and sets the event accordingly
+ protected void setApplicationEventHandled(Object event, boolean handled) {
+ if (event != null) {
+ try {
+ Method setHandledMethod = event.getClass().getDeclaredMethod("setHandled", new Class[] { boolean.class });
+ // If the target method returns a boolean, use that as a hint
+ setHandledMethod.invoke(event, new Object[] { Boolean.valueOf(handled) });
+ } catch (Exception ex) {
+ System.err.println("OSXAdapter was unable to handle an ApplicationEvent: " + event);
+ ex.printStackTrace();
+ }
+ }
+ }
+}
--- /dev/null
+#!/bin/sh
+
+VERSION=1.0
+PRODUCT=EasyMega
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Keith Packard. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ for igniter in drogue main 0 1 2 3; do
+ echo "Testing $igniter igniter."
+ echo -n "Press enter to continue..."
+ read foo < /dev/tty
+ ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $igniter
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ ;;
+ esac
+ done
+
+ echo "Testing baro sensor"
+ ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ FLASHSIZE=8388608
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ ret=0
+ ;;
+ *)
+ echo "Skipping $product $serial $dev"
+ ;;
+ esac
+done
echo "Testing $product $serial $dev"
echo "Testing igniters. Both should flash"
- ./test-igniter "$dev" drogue main
+ ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" drogue main
case $? in
0)
esac
echo "Testing baro sensor"
- ./test-baro "$dev"
+ ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
case $? in
0)
FLASHSIZE=1048576
echo "Testing flash"
- ./test-flash "$dev" "$FLASHSIZE"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
case $? in
0)
string[*] sats = find_gps(i, "Sats:");
int actual_flags = string_to_integer(flags[1]);
+ int actual_sats = string_to_integer(sats[1]);
while ((actual_flags & (1 << 4)) == 0) {
printf("Flags: %s\n", flags[1]);
exit 1
esac
- echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests
ret=0
;;
*)
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+ STMLOAD=/usr/bin/ao-flash-stm
+else
+ echo "Can't find ao-flash-stm! Aborting."
+ exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=1.0
+REPO=~/altusmetrumllc/Binaries
+
+echo "EasyMega v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\tEasyMega v$VERSION"
+echo "\t\twith USB cable attached"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo
+echo -n "EasyMega-$VERSION serial number: "
+read SERIAL
+
+echo $STMLOAD
+
+$STMLOAD $REPO/loaders/easymega-v$VERSION*.elf || exit 1
+
+sleep 2
+
+$USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1
+
+sleep 2
+
+dev=`ao-list | awk '/EasyMega-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "EasyMega found on $dev"
+ ;;
+*)
+ echo 'No EasyMega-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+../ao-tools/ao-cal-accel/ao-cal-accel $dev
+
+echo 'E 1' > $dev
+
+./test-easymega
+
+exit $?
SERIAL=$SERIAL ./cal-freq $dev
-./cal-accel $dev
+../ao-tools/ao-cal-accel/ao-cal-accel $dev
+
+echo 'E 1' > $dev
#!/bin/sh
-if [ -x ../ao-tools/ao-stmload/ao-stmload ]; then
- STMLOAD=../ao-tools/ao-stmload/ao-stmload
-elif [ -x /usr/bin/ao-stmload ]; then
- STMLOAD=/usr/bin/ao-stmload
+if [ -x /usr/bin/ao-flash-stm ]; then
+ FLASH_STM=/usr/bin/ao-flash-stm
else
- echo "Can't find ao-stmload! Aborting."
+ echo "Can't find ao-flash-stm! Aborting."
exit 1
fi
-if [ -x ../ao-tools/ao-usbload/ao-usbload ]; then
- USBLOAD=../ao-tools/ao-usbload/ao-usbload
-elif [ -x /usr/bin/ao-usbload ]; then
+if [ -x /usr/bin/ao-usbload ]; then
USBLOAD=/usr/bin/ao-usbload
else
echo "Can't find ao-usbload! Aborting."
echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
echo
echo "Expectations:"
-echo "\tTeleMetrum v$VERSIOn powered from USB"
+echo "\tTeleMetrum v$VERSION powered from USB"
echo "\t\twith ST-Link-V2 cabled to debug header"
echo "\t\twith coax from UHF to frequency counter"
echo
echo -n "TeleMetrum-$VERSION serial number: "
read SERIAL
-echo $STMLOAD
+echo $FLASH_STM
-$STMLOAD --raw ../src/telemetrum-v$VERSION/flash-loader/*.elf || exit 1
+$FLASH_STM ~/altusmetrumllc/Binaries/loaders/telemetrum-v$VERSION-*.elf || exit 1
sleep 2
SERIAL=$SERIAL ./cal-freq $dev
-./cal-accel $dev
+../ao-tools/ao-cal-accel/ao-cal-accel $dev
+
+echo 'E 1' > $dev
SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \
ao-load ao-telem ao-send-telem ao-sky-flash \
ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \
- ao-flash ao-usbload
+ ao-flash ao-usbload ao-test-igniter ao-test-baro \
+ ao-test-flash ao-cal-accel
if LIBSTLINK
SUBDIRS += ao-stmload
endif
--- /dev/null
+ao-cal-accel
--- /dev/null
+bin_PROGRAMS=ao-cal-accel
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_cal_accel_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_cal_accel_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_cal_accel_SOURCES=ao-cal-accel.c
+
+man_MANS = ao-cal-accel.1
--- /dev/null
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-cal-accel" ""
+.SH NAME
+ao-cal-accel \- Calibrate AltOS flight computer accelerometers
+.SH SYNOPSIS
+.B "ao-cal-accel"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+.SH DESCRIPTION
+.I ao-cal-accel
+drives the built-in accelerometer calibration and validates the results.
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-cal-accel
+opens the target device, executes the accelerometer calibration
+command, verifies that it executed correctly, then shows the resulting
+calibration values and saves them to configuration memory.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include <termios.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "raw", .has_arg = 0, .val = 'r' },
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>]\n", program);
+ exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+ cc_usb_close(cc);
+ exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+ int whole_len = strlen(whole);
+ int prefix_len = strlen(prefix);
+
+ if (prefix_len > whole_len)
+ return 0;
+ return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+static char **
+tok(char *line) {
+ char **strs = malloc (sizeof (char *)), *str;
+ int n = 0;
+
+ while ((str = strtok(line, " \t"))) {
+ line = NULL;
+ strs = realloc(strs, (n + 2) * sizeof (char *));
+ strs[n] = strdup(str);
+ n++;
+ }
+ strs[n] = '\0';
+ return strs;
+}
+
+static void
+free_strs(char **strs) {
+ char *str;
+ int i;
+
+ for (i = 0; (str = strs[i]) != NULL; i++)
+ free(str);
+ free(strs);
+}
+
+struct flash {
+ struct flash *next;
+ char line[512];
+ char **strs;
+};
+
+static struct flash *
+flash(struct cc_usb *usb)
+{
+ struct flash *head = NULL, **tail = &head;
+ cc_usb_printf(usb, "c s\nv\n");
+ for (;;) {
+ char line[512];
+ struct flash *b;
+
+ cc_usb_getline(usb, line, sizeof (line));
+ b = malloc (sizeof (struct flash));
+ strcpy(b->line, line);
+ b->strs = tok(line);
+ b->next = NULL;
+ *tail = b;
+ tail = &b->next;
+ if (strstr(line, "software-version"))
+ break;
+ }
+ return head;
+}
+
+static void
+free_flash(struct flash *b) {
+ struct flash *n;
+
+ while (b) {
+ n = b->next;
+ free_strs(b->strs);
+ free(b);
+ b = n;
+ }
+}
+
+char **
+find_flash(struct flash *b, char *word0) {
+ int i;
+ for (;b; b = b->next) {
+ if (strstr(b->line, word0))
+ return b->strs;
+ }
+ return NULL;
+}
+
+void
+await_key(void)
+{
+ struct termios termios, termios_save;
+ char buf[512];
+
+ tcgetattr(0, &termios);
+ termios_save = termios;
+ cfmakeraw(&termios);
+ tcsetattr(0, TCSAFLUSH, &termios);
+ read(0, buf, sizeof (buf));
+ tcsetattr(0, TCSAFLUSH, &termios_save);
+}
+
+int
+do_cal(struct cc_usb *usb) {
+ struct flash *b;
+ char **accel;
+ char line[1024];
+ int l;
+ int running = 0;
+ int worked = 1;
+
+ cc_usb_printf(usb, "E 1\nc a 0\n");
+
+ for (;;) {
+ int c = cc_usb_getchar_timeout(usb, 20*1000);
+
+ if (c == '\n')
+ l = 0;
+ else if (l < sizeof (line) - 1)
+ line[l++] = c;
+ line[l] = '\0';
+ putchar(c); fflush(stdout);
+ if (strstr(line, "press a key...")) {
+ await_key();
+ cc_usb_printf(usb, " ");
+ l = 0;
+ running = 1;
+ }
+ else if (strstr(line, "Invalid"))
+ worked = 0;
+ if (running && strstr(line, ">")) {
+ printf("\n");
+ break;
+ }
+ }
+ cc_usb_printf(usb, "E 0\n");
+
+ if (!worked) {
+ printf("Calibration failed\n");
+ return 0;
+ }
+
+ b = flash(usb);
+
+ accel = find_flash(b, "Accel cal");
+ if (!accel) {
+ printf("no response\n");
+ return 0;
+ }
+
+ printf ("Accel cal +1g: %s -1g: %s\n",
+ accel[3], accel[5]);
+
+ printf ("Saving..."); fflush(stdout);
+ cc_usb_printf (usb, "c w\n");
+ cc_usb_sync(usb);
+ b = flash(usb);
+ printf ("done\n");
+
+ return worked;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *device = NULL;
+ char *filename;
+ Elf *e;
+ unsigned int s;
+ int i;
+ int c;
+ int tries;
+ struct cc_usb *cc = NULL;
+ char *tty = NULL;
+ int success;
+ int verbose = 0;
+ int ret = 0;
+ int expected_size;
+
+ while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ ao_verbose = verbose;
+
+ if (verbose > 1)
+ ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+ if (!tty)
+ tty = getenv("ALTOS_TTY");
+ if (!tty)
+ tty="/dev/ttyACM0";
+
+ cc = cc_usb_open(tty);
+
+ if (!cc)
+ exit(1);
+
+ if (!do_cal(cc))
+ ret = 1;
+ done(cc, ret);
+}
case AO_TELEMETRY_MEGA_DATA:
cur_state = telem->mega_data.state;
break;
+ case AO_TELEMETRY_METRUM_SENSOR:
+ cur_state = telem->metrum_sensor.state;
+ break;
+ case AO_TELEMETRY_MINI:
+ cur_state = telem->mini.state;
+ break;
}
return cur_state;
}
--- /dev/null
+ao-test-baro
--- /dev/null
+bin_PROGRAMS=ao-test-baro
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_test_baro_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_test_baro_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_test_baro_SOURCES=ao-test-baro.c
+
+man_MANS = ao-test-baro.1
--- /dev/null
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-test-baro" ""
+.SH NAME
+ao-test-baro \- test AltOS flight computer barometric sensor
+.SH SYNOPSIS
+.B "ao-test-baro"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIbaro-name...\fP
+.SH DESCRIPTION
+.I ao-test-baro
+makes sure the altitude is between -50m and 3000m and temperature is
+between 20°C and 30°C.
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-test-baro
+opens the target device and queries the current barometric data.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "raw", .has_arg = 0, .val = 'r' },
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] main|drogue\n", program);
+ exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+/* cc_usb_printf(cc, "a\n"); */
+ cc_usb_close(cc);
+ exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+ int whole_len = strlen(whole);
+ int prefix_len = strlen(prefix);
+
+ if (prefix_len > whole_len)
+ return 0;
+ return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+static char **
+tok(char *line) {
+ char **strs = malloc (sizeof (char *)), *str;
+ int n = 0;
+
+ while ((str = strtok(line, " \t"))) {
+ line = NULL;
+ strs = realloc(strs, (n + 2) * sizeof (char *));
+ strs[n] = strdup(str);
+ n++;
+ }
+ strs[n] = '\0';
+ return strs;
+}
+
+static void
+free_strs(char **strs) {
+ char *str;
+ int i;
+
+ for (i = 0; (str = strs[i]) != NULL; i++)
+ free(str);
+ free(strs);
+}
+
+struct baro {
+ struct baro *next;
+ char **strs;
+};
+
+static struct baro *
+baro(struct cc_usb *usb)
+{
+ struct baro *head = NULL, **tail = &head;
+ cc_usb_printf(usb, "B\n");
+ for (;;) {
+ char line[512];
+ struct baro *b;
+
+ cc_usb_getline(usb, line, sizeof (line));
+ b = malloc (sizeof (struct baro));
+ b->strs = tok(line);
+ b->next = NULL;
+ *tail = b;
+ tail = &b->next;
+ if (strstr(line, "Altitude:"))
+ break;
+ }
+ return head;
+}
+
+static void
+free_baro(struct baro *b) {
+ struct baro *n;
+
+ while (b) {
+ n = b->next;
+ free_strs(b->strs);
+ free(b);
+ b = n;
+ }
+}
+
+char **
+find_baro(struct baro *b, char *word0) {
+ int i;
+ for (;b; b = b->next)
+ if (b->strs[0] && !strcmp(b->strs[0], word0))
+ return b->strs;
+ return NULL;
+}
+
+int
+do_baro(struct cc_usb *usb) {
+ struct baro *b = baro(usb);
+ char **temp = find_baro(b, "Temperature:");
+ char **alt = find_baro(b, "Altitude:");
+
+ if (!temp || !alt) {
+ printf("no response\n");
+ free_baro(b);
+ return 0;
+ }
+
+ double temperature = strtod(temp[2], NULL) / 100.0;
+ double altitude = strtod(alt[1], NULL);
+
+ if (altitude < -50 || 3000 < altitude) {
+ printf ("weird altitude %f\n", altitude);
+ free_baro(b);
+ return 0;
+ }
+
+ if (temperature < 20 || 35 < temperature) {
+ printf ("weird temperature %f\n", temperature);
+ free_baro(b);
+ return 0;
+ }
+
+ printf ("altitude %f temperature %f\n", altitude, temperature);
+
+ return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *device = NULL;
+ char *filename;
+ Elf *e;
+ unsigned int s;
+ int i;
+ int c;
+ int tries;
+ struct cc_usb *cc = NULL;
+ char *tty = NULL;
+ int success;
+ int verbose = 0;
+ int ret = 0;
+
+ while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ ao_verbose = verbose;
+
+ if (verbose > 1)
+ ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+ if (!tty)
+ tty = getenv("ALTOS_TTY");
+ if (!tty)
+ tty="/dev/ttyACM0";
+
+ cc = cc_usb_open(tty);
+
+ if (!cc)
+ exit(1);
+
+ if (!do_baro(cc))
+ ret = 1;
+ done(cc, ret);
+}
--- /dev/null
+ao-test-flash
--- /dev/null
+bin_PROGRAMS=ao-test-flash
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_test_flash_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_test_flash_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_test_flash_SOURCES=ao-test-flash.c
+
+man_MANS = ao-test-flash.1
--- /dev/null
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-test-igniter" ""
+.SH NAME
+ao-test-igniter \- test AltOS flight computer igniters
+.SH SYNOPSIS
+.B "ao-test-igniter"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIigniter-name...\fP
+.SH DESCRIPTION
+.I ao-test-igniter
+test the status and then fires the specified igniters on the target device
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-test-igniter
+opens the target device, lists the available igniter and then fires
+the specified ones. And error occurrs if any of the specified igniters
+is not present or not ready.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "raw", .has_arg = 0, .val = 'r' },
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] <expected-size>\n", program);
+ exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+ cc_usb_close(cc);
+ exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+ int whole_len = strlen(whole);
+ int prefix_len = strlen(prefix);
+
+ if (prefix_len > whole_len)
+ return 0;
+ return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+static char **
+tok(char *line) {
+ char **strs = malloc (sizeof (char *)), *str;
+ int n = 0;
+
+ while ((str = strtok(line, " \t"))) {
+ line = NULL;
+ strs = realloc(strs, (n + 2) * sizeof (char *));
+ strs[n] = strdup(str);
+ n++;
+ }
+ strs[n] = '\0';
+ return strs;
+}
+
+static void
+free_strs(char **strs) {
+ char *str;
+ int i;
+
+ for (i = 0; (str = strs[i]) != NULL; i++)
+ free(str);
+ free(strs);
+}
+
+struct flash {
+ struct flash *next;
+ char line[512];
+ char **strs;
+};
+
+static struct flash *
+flash(struct cc_usb *usb)
+{
+ struct flash *head = NULL, **tail = &head;
+ cc_usb_printf(usb, "f\nv\n");
+ for (;;) {
+ char line[512];
+ struct flash *b;
+
+ cc_usb_getline(usb, line, sizeof (line));
+ b = malloc (sizeof (struct flash));
+ strcpy(b->line, line);
+ b->strs = tok(line);
+ b->next = NULL;
+ *tail = b;
+ tail = &b->next;
+ if (strstr(line, "software-version"))
+ break;
+ }
+ return head;
+}
+
+static void
+free_flash(struct flash *b) {
+ struct flash *n;
+
+ while (b) {
+ n = b->next;
+ free_strs(b->strs);
+ free(b);
+ b = n;
+ }
+}
+
+char **
+find_flash(struct flash *b, char *word0) {
+ int i;
+ for (;b; b = b->next) {
+ if (strstr(b->line, word0))
+ return b->strs;
+ }
+ return NULL;
+}
+
+int
+do_flash(struct cc_usb *usb, int expected_size) {
+ struct flash *b = flash(usb);
+ char **size = find_flash(b, "Storage size:");
+ char **erase = find_flash(b, "Storage erase unit:");
+
+ if (!size || !erase) {
+ printf("no response\n");
+ free_flash(b);
+ return 0;
+ }
+
+ int actual_size = atoi(size[2]);
+
+ if (actual_size != expected_size) {
+ printf ("weird flash size %d != %d\n", actual_size, expected_size);
+ free_flash(b);
+ return 0;
+ }
+
+ int actual_erase = atoi(erase[3]);
+
+ if (actual_erase != 65536) {
+ printf ("weird erase size %d\n", actual_erase);
+ free_flash(b);
+ return 0;
+ }
+
+ printf ("flash size %d erase block %d\n", actual_size, actual_erase);
+
+ return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *device = NULL;
+ char *filename;
+ Elf *e;
+ unsigned int s;
+ int i;
+ int c;
+ int tries;
+ struct cc_usb *cc = NULL;
+ char *tty = NULL;
+ int success;
+ int verbose = 0;
+ int ret = 0;
+ int expected_size;
+
+ while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if (!argv[optind])
+ usage(argv[0]);
+
+ ao_verbose = verbose;
+
+ if (verbose > 1)
+ ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+ if (!tty)
+ tty = getenv("ALTOS_TTY");
+ if (!tty)
+ tty="/dev/ttyACM0";
+
+ cc = cc_usb_open(tty);
+
+ if (!cc)
+ exit(1);
+
+ if (!do_flash(cc, atoi(argv[optind])))
+ ret = 1;
+ done(cc, ret);
+}
--- /dev/null
+ao-test-igniter
--- /dev/null
+bin_PROGRAMS=ao-test-igniter
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_test_igniter_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_test_igniter_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_test_igniter_SOURCES=ao-test-igniter.c
+
+man_MANS = ao-test-igniter.1
--- /dev/null
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-test-igniter" ""
+.SH NAME
+ao-test-igniter \- test AltOS flight computer igniters
+.SH SYNOPSIS
+.B "ao-test-igniter"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIigniter-name...\fP
+.SH DESCRIPTION
+.I ao-test-igniter
+test the status and then fires the specified igniters on the target device
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-test-igniter
+opens the target device, lists the available igniter and then fires
+the specified ones. And error occurrs if any of the specified igniters
+is not present or not ready.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "raw", .has_arg = 0, .val = 'r' },
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] main|drogue\n", program);
+ exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+/* cc_usb_printf(cc, "a\n"); */
+ cc_usb_close(cc);
+ exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static int
+starts_with(char *whole, char *prefix)
+{
+ int whole_len = strlen(whole);
+ int prefix_len = strlen(prefix);
+
+ if (prefix_len > whole_len)
+ return 0;
+ return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+struct igniter {
+ struct igniter *next;
+ char name[512];
+ char status[512];
+};
+
+static struct igniter *
+igniters(struct cc_usb *usb)
+{
+ struct igniter *head = NULL, **tail = &head;
+ cc_usb_printf(usb, "t\nv\n");
+ for (;;) {
+ char line[512];
+ char name[512];
+ char status[512];
+
+ cc_usb_getline(usb, line, sizeof (line));
+ if (strstr(line, "software-version"))
+ break;
+ if (sscanf(line, "Igniter: %s Status: %s", &name, &status) == 2) {
+ struct igniter *i = malloc (sizeof (struct igniter));
+ strcpy(i->name, name);
+ strcpy(i->status, status);
+ i->next = NULL;
+ *tail = i;
+ tail = &i->next;
+ }
+ }
+ return head;
+}
+
+static void
+free_igniters(struct igniter *i) {
+ struct igniter *n;
+
+ while (i) {
+ n = i->next;
+ free(i);
+ i = n;
+ }
+}
+
+static struct igniter *
+find_igniter(struct igniter *i, char *name)
+{
+ for (; i; i = i->next)
+ if (strcmp(i->name, name) == 0)
+ return i;
+}
+
+static int
+do_igniter(struct cc_usb *usb, char *name)
+{
+ struct igniter *all = igniters(usb);
+ struct igniter *this = find_igniter(all, name);
+ if (!this) {
+ struct igniter *i;
+ printf("no igniter %s found in");
+ for (i = all; i; i = i->next)
+ printf(" %s", i->name);
+ printf("\n");
+ free_igniters(all);
+ return 0;
+ }
+ if (strcmp(this->status, "ready") != 0) {
+ printf("igniter %s status is %s\n", this->name, this->status);
+ free_igniters(all);
+ return 0;
+ }
+ cc_usb_printf(usb, "i DoIt %s\n", this->name);
+ cc_usb_sync(usb);
+ free_igniters(all);
+ usleep(200000);
+ return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *device = NULL;
+ char *filename;
+ Elf *e;
+ unsigned int s;
+ int i;
+ int c;
+ int tries;
+ struct cc_usb *cc = NULL;
+ char *tty = NULL;
+ int success;
+ int verbose = 0;
+ int ret = 0;
+
+ while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ ao_verbose = verbose;
+
+ if (verbose > 1)
+ ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+ printf ("device %s\n", device);
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleMega-v1.0");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleMetrum-v2.0");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleMini-v2.0");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "EasyMega-v1.0");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "EasyMetrum-v1.0");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "EasyMini-v1.0");
+ if (!tty)
+ tty = getenv("ALTOS_TTY");
+ if (!tty)
+ tty="/dev/ttyACM0";
+
+ cc = cc_usb_open(tty);
+
+ if (!cc)
+ exit(1);
+
+ for (i = optind; i < argc; i++) {
+ char *name = argv[i];
+
+ if (!do_igniter(cc, name))
+ ret++;
+ }
+ done(cc, ret);
+}
return pressure;
}
+double
+cc_altitude_to_temperature(double altitude)
+{
+
+ double base_temperature = LAYER0_BASE_TEMPERATURE;
+ double temperature;
+
+ int layer_number; /* identifies layer in the atmosphere */
+ double delta_z; /* difference between two altitudes */
+
+ /* calculate the base temperature for the atmospheric layer
+ associated with the inputted altitude */
+ for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) {
+ delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
+ base_temperature += delta_z * lapse_rate[layer_number];
+ }
+
+ /* calculate the pressure at the inputted altitude */
+ delta_z = altitude - base_altitude[layer_number];
+ temperature = base_temperature + lapse_rate[layer_number] * delta_z;
+
+ return temperature - 273.15;
+}
/* outputs the altitude associated with the given pressure. the altitude
returned is measured with respect to the mean sea level */
} u;
};
+struct ao_log_metrum {
+ char type; /* 0 */
+ uint8_t csum; /* 1 */
+ uint16_t tick; /* 2 */
+ union { /* 4 */
+ /* AO_LOG_FLIGHT */
+ struct {
+ uint16_t flight; /* 4 */
+ int16_t ground_accel; /* 6 */
+ uint32_t ground_pres; /* 8 */
+ uint32_t ground_temp; /* 12 */
+ } flight; /* 16 */
+ /* AO_LOG_STATE */
+ struct {
+ uint16_t state; /* 4 */
+ uint16_t reason; /* 6 */
+ } state; /* 8 */
+ /* AO_LOG_SENSOR */
+ struct {
+ uint32_t pres; /* 4 */
+ uint32_t temp; /* 8 */
+ int16_t accel; /* 12 */
+ } sensor; /* 14 */
+ /* AO_LOG_TEMP_VOLT */
+ struct {
+ int16_t v_batt; /* 4 */
+ int16_t sense_a; /* 6 */
+ int16_t sense_m; /* 8 */
+ } volt; /* 10 */
+ /* AO_LOG_GPS_POS */
+ struct {
+ int32_t latitude; /* 4 */
+ int32_t longitude; /* 8 */
+ uint16_t altitude_low; /* 12 */
+ int16_t altitude_high; /* 14 */
+ } gps; /* 16 */
+ /* AO_LOG_GPS_TIME */
+ struct {
+ uint8_t hour; /* 4 */
+ uint8_t minute; /* 5 */
+ uint8_t second; /* 6 */
+ uint8_t flags; /* 7 */
+ uint8_t year; /* 8 */
+ uint8_t month; /* 9 */
+ uint8_t day; /* 10 */
+ uint8_t pdop; /* 11 */
+ } gps_time; /* 12 */
+ /* AO_LOG_GPS_SAT (up to three packets) */
+ struct {
+ uint8_t channels; /* 4 */
+ uint8_t more; /* 5 */
+ struct {
+ uint8_t svid;
+ uint8_t c_n;
+ } sats[4]; /* 6 */
+ } gps_sat; /* 14 */
+ uint8_t raw[12]; /* 4 */
+ } u; /* 16 */
+};
+
+struct ao_log_mini {
+ char type; /* 0 */
+ uint8_t csum; /* 1 */
+ uint16_t tick; /* 2 */
+ union { /* 4 */
+ /* AO_LOG_FLIGHT */
+ struct {
+ uint16_t flight; /* 4 */
+ uint16_t r6;
+ uint32_t ground_pres; /* 8 */
+ } flight;
+ /* AO_LOG_STATE */
+ struct {
+ uint16_t state; /* 4 */
+ uint16_t reason; /* 6 */
+ } state;
+ /* AO_LOG_SENSOR */
+ struct {
+ uint8_t pres[3]; /* 4 */
+ uint8_t temp[3]; /* 7 */
+ int16_t sense_a; /* 10 */
+ int16_t sense_m; /* 12 */
+ int16_t v_batt; /* 14 */
+ } sensor; /* 16 */
+ } u; /* 16 */
+}; /* 16 */
+
+#define ao_log_pack24(dst,value) do { \
+ (dst)[0] = (value); \
+ (dst)[1] = (value) >> 8; \
+ (dst)[2] = (value) >> 16; \
+ } while (0)
+
+struct ao_log_gps {
+ char type; /* 0 */
+ uint8_t csum; /* 1 */
+ uint16_t tick; /* 2 */
+ union { /* 4 */
+ /* AO_LOG_FLIGHT */
+ struct {
+ uint16_t flight; /* 4 */
+ int16_t start_altitude; /* 6 */
+ int32_t start_latitude; /* 8 */
+ int32_t start_longitude; /* 12 */
+ } flight; /* 16 */
+ /* AO_LOG_GPS_TIME */
+ struct {
+ int32_t latitude; /* 4 */
+ int32_t longitude; /* 8 */
+ uint16_t altitude_low; /* 12 */
+ uint8_t hour; /* 14 */
+ uint8_t minute; /* 15 */
+ uint8_t second; /* 16 */
+ uint8_t flags; /* 17 */
+ uint8_t year; /* 18 */
+ uint8_t month; /* 19 */
+ uint8_t day; /* 20 */
+ uint8_t course; /* 21 */
+ uint16_t ground_speed; /* 22 */
+ int16_t climb_rate; /* 24 */
+ uint8_t pdop; /* 26 */
+ uint8_t hdop; /* 27 */
+ uint8_t vdop; /* 28 */
+ uint8_t mode; /* 29 */
+ int16_t altitude_high; /* 30 */
+ } gps; /* 31 */
+ /* AO_LOG_GPS_SAT */
+ struct {
+ uint16_t channels; /* 4 */
+ struct {
+ uint8_t svid;
+ uint8_t c_n;
+ } sats[12]; /* 6 */
+ } gps_sat; /* 30 */
+ } u;
+};
+
#define AO_CONFIG_CONFIG 1
#define AO_CONFIG_MAIN 2
#define AO_CONFIG_APOGEE 3
#define AO_LOG_GPS_ALT 'H'
#define AO_LOG_GPS_SAT 'V'
#define AO_LOG_GPS_DATE 'Y'
+#define AO_LOG_GPS_POS 'P'
#define AO_LOG_CONFIG 'c'
+#define AO_GPS_NUM_SAT_MASK (0xf << 0)
+#define AO_GPS_NUM_SAT_SHIFT (0)
+
+#define AO_GPS_VALID (1 << 4)
+#define AO_GPS_RUNNING (1 << 5)
+#define AO_GPS_DATE_VALID (1 << 6)
+#define AO_GPS_COURSE_VALID (1 << 7)
+
+#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */
+#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */
+#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */
+#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */
+#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */
+#define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */
+#define AO_LOG_FORMAT_EASYMINI 6 /* 16-byte MS5607 baro only, 3.0V supply */
+#define AO_LOG_FORMAT_TELEMETRUM 7 /* 16-byte typed telemetrum records */
+#define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */
+#define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */
+#define AO_LOG_FORMAT_NONE 127 /* No log at all */
+
int
cc_mega_parse(const char *input_line, struct ao_log_mega *l);
double
cc_altitude_to_pressure(double altitude);
+double
+cc_altitude_to_temperature(double altitude);
+
double
cc_barometer_to_pressure(double baro);
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.4.1)
+AC_INIT([altos], 1.5)
AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
dnl ==========================================================================
dnl Java library versions
-ALTOSUILIB_VERSION=2
-ALTOSLIB_VERSION=4
+ALTOSUILIB_VERSION=3
+ALTOSLIB_VERSION=5
AC_SUBST(ALTOSLIB_VERSION)
AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
xx86_64|xi*86)
save_CFLAGS="$CFLAGS"
save_LIBS="$LIBS"
- LIBS="-lbluetooth"
+ LIBS="-ldl"
CFLAGS="-m64"
AC_MSG_CHECKING([if ]$CC[ ]$CFLAGS[ can link programs])
AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
ao-tools/ao-elftohex/Makefile
ao-tools/ao-usbload/Makefile
ao-tools/ao-flash/Makefile
+ao-tools/ao-test-igniter/Makefile
+ao-tools/ao-test-baro/Makefile
+ao-tools/ao-test-flash/Makefile
+ao-tools/ao-cal-accel/Makefile
ao-utils/Makefile
src/Version
])
release-notes-1.3.1.html \
release-notes-1.3.2.html \
release-notes-1.4.html \
- release-notes-1.4.1.html
+ release-notes-1.4.1.html \
+ release-notes-1.5.html
PICTURES=\
altosui.png \
easymini.svg \
telemega.svg \
telemetrum.svg \
- telemini.svg
+ telemini.svg \
+ easymega.svg
RELNOTES_XSL=$(RELNOTES:.html=.xsl)
HTML=altusmetrum.html altos.html telemetry.html companion.html micropeak.html telegps.html $(RELNOTES)
PDF=altusmetrum.pdf altos.pdf telemetry.pdf companion.pdf micropeak.pdf telegps.pdf \
- telemetrum-outline.pdf telemega-outline.pdf easymini-outline.pdf
+ telemetrum-outline.pdf telemega-outline.pdf easymini-outline.pdf easymega-outline.pdf
HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl
FOSTYLE=xorg-fo.xsl
TEMPLATES=titlepage.templates.xsl
</para>
</legalnotice>
<revhistory>
+ <revision>
+ <revnumber>1.5</revnumber>
+ <date>6 September 2014</date>
+ <revremark>
+ Major release adding EasyMega support.
+ </revremark>
+ </revision>
<revision>
<revnumber>1.4.1</revnumber>
- <date>24 June 2014</date>
+ <date>20 June 2014</date>
<revremark>
Minor release fixing some installation bugs.
</revremark>
EasyMini is a dual-deploy altimeter with logging and built-in
USB data download.
</para>
+ <para>
+ EasyMega is essentially a TeleMega board with the GPS receiver
+ and telemetry transmitter removed. It offers the same 6 pyro
+ channels and integrated gyroscopes for staging/air-start inhibit.
+ </para>
<para>
TeleDongle was our first ground station, providing a USB to RF
interfaces for communicating with the altimeters. Combined with
“starter kit” is to charge the battery.
</para>
<para>
- For TeleMetrum and TeleMega, the battery can be charged by plugging it into the
+ For TeleMetrum, TeleMega and EasyMega, the battery can be charged by plugging it into the
corresponding socket of the device and then using the USB
cable to plug the flight computer into your computer's USB socket. The
on-board circuitry will charge the battery whenever it is plugged
deeply discharged battery.
</para>
<para>
- TeleMetrum v2.0 and TeleMega use a higher power battery charger,
+ TeleMetrum v2.0, TeleMega and EasyMega use a higher power battery charger,
allowing them to charge the battery while running the board at
maximum power. When the battery is charging, or when the board
is consuming a lot of power, the red LED will be lit. When the
EasyMini and TeleMini v2 are designed to use either a
lithium polymer battery or any other battery producing
between 4 and 12 volts, such as a rectangular 9V
- battery. TeleMega and TeleMetrum are not designed for this,
+ battery. TeleMega, EasyMega and TeleMetrum are not designed for this,
and must only be powered by a lithium polymer battery. Find
instructions on how to use other batteries in the EasyMini
and TeleMini sections below.
<entry>40mW</entry>
<entry>3.7V</entry>
</row>
+ <row>
+ <entry>EasyMega <?linebreak?>v1.0</entry>
+ <entry><para>MS5607 30km (100k')</para></entry>
+ <entry><para>MMA6555 102g</para></entry>
+ <entry>-</entry>
+ <entry><para>MPU6000 HMC5883</para></entry>
+ <entry>8MB</entry>
+ <entry>-</entry>
+ <entry>3.7V</entry>
+ </row>
</tbody>
</tgroup>
</table>
<entry>3¼ inch (8.26cm)</entry>
<entry>38mm coupler</entry>
</row>
+ <row>
+ <entry>EasyMega</entry>
+ <entry><para>
+ Debug<?linebreak?>
+ Companion<?linebreak?>
+ USB<?linebreak?>
+ Battery
+ </para></entry>
+ <entry><para>
+ Apogee pyro <?linebreak?>
+ Main pyro<?linebreak?>
+ Pyro A-D<?linebreak?>
+ Switch<?linebreak?>
+ Pyro battery
+ </para></entry>
+ <entry>1¼ inch (3.18cm)</entry>
+ <entry>2¼ inch (5.62cm)</entry>
+ <entry>38mm coupler</entry>
+ </row>
</tbody>
</tgroup>
</table>
</para>
</section>
</section>
+ <section>
+ <title>EasyMega</title>
+ <informalfigure>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="easymega-v1.0-top.jpg" width="4.5in" scalefit="1"/>
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ <para>
+ EasyMega is a 1¼ inch by 2¼ inch circuit board. It was
+ designed to easily fit in a 38mm coupler. Like TeleMetrum,
+ EasyMega has an accelerometer and so it must be mounted so that
+ the board is aligned with the flight axis. It can be mounted
+ either antenna up or down.
+ </para>
+ <section>
+ <title>EasyMega Screw Terminals</title>
+ <para>
+ EasyMega has two sets of nine screw terminals on the end of
+ the board opposite the telemetry antenna. They are as follows:
+ </para>
+ <table frame='all'>
+ <title>EasyMega Screw Terminals</title>
+ <?dbfo keep-together="always"?>
+ <tgroup cols='3' align='center' colsep='1' rowsep='1'>
+ <colspec align='center' colwidth='*' colname='Pin #'/>
+ <colspec align='center' colwidth='2*' colname='Pin Name'/>
+ <colspec align='left' colwidth='5*' colname='Description'/>
+ <thead>
+ <row>
+ <entry align='center'>Terminal #</entry>
+ <entry align='center'>Terminal Name</entry>
+ <entry align='center'>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Top 1</entry>
+ <entry>Switch Input</entry>
+ <entry>Switch connection to positive battery terminal</entry>
+ </row>
+ <row>
+ <entry>Top 2</entry>
+ <entry>Switch Output</entry>
+ <entry>Switch connection to flight computer</entry>
+ </row>
+ <row>
+ <entry>Top 3</entry>
+ <entry>GND</entry>
+ <entry>Ground connection for use with external active switch</entry>
+ </row>
+ <row>
+ <entry>Top 4</entry>
+ <entry>Main -</entry>
+ <entry>Main pyro channel connection to pyro circuit</entry>
+ </row>
+ <row>
+ <entry>Top 5</entry>
+ <entry>Main +</entry>
+ <entry>Main pyro channel common connection to battery +</entry>
+ </row>
+ <row>
+ <entry>Top 6</entry>
+ <entry>Apogee -</entry>
+ <entry>Apogee pyro channel connection to pyro circuit</entry>
+ </row>
+ <row>
+ <entry>Top 7</entry>
+ <entry>Apogee +</entry>
+ <entry>Apogee pyro channel common connection to battery +</entry>
+ </row>
+ <row>
+ <entry>Top 8</entry>
+ <entry>D -</entry>
+ <entry>D pyro channel connection to pyro circuit</entry>
+ </row>
+ <row>
+ <entry>Top 9</entry>
+ <entry>D +</entry>
+ <entry>D pyro channel common connection to battery +</entry>
+ </row>
+ <row>
+ <entry>Bottom 1</entry>
+ <entry>GND</entry>
+ <entry>Ground connection for negative pyro battery terminal</entry>
+ </row>
+ <row>
+ <entry>Bottom 2</entry>
+ <entry>Pyro</entry>
+ <entry>Positive pyro battery terminal</entry>
+ </row>
+ <row>
+ <entry>Bottom 3</entry>
+ <entry>Lipo</entry>
+ <entry>
+ Power switch output. Use to connect main battery to
+ pyro battery input
+ </entry>
+ </row>
+ <row>
+ <entry>Bottom 4</entry>
+ <entry>A -</entry>
+ <entry>A pyro channel connection to pyro circuit</entry>
+ </row>
+ <row>
+ <entry>Bottom 5</entry>
+ <entry>A +</entry>
+ <entry>A pyro channel common connection to battery +</entry>
+ </row>
+ <row>
+ <entry>Bottom 6</entry>
+ <entry>B -</entry>
+ <entry>B pyro channel connection to pyro circuit</entry>
+ </row>
+ <row>
+ <entry>Bottom 7</entry>
+ <entry>B +</entry>
+ <entry>B pyro channel common connection to battery +</entry>
+ </row>
+ <row>
+ <entry>Bottom 8</entry>
+ <entry>C -</entry>
+ <entry>C pyro channel connection to pyro circuit</entry>
+ </row>
+ <row>
+ <entry>Bottom 9</entry>
+ <entry>C +</entry>
+ <entry>C pyro channel common connection to battery +</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section>
+ <title>Using a Separate Pyro Battery with EasyMega</title>
+ <para>
+ EasyMega provides explicit support for an external pyro
+ battery. All that is required is to remove the jumper
+ between the lipo terminal (Bottom 3) and the pyro terminal
+ (Bottom 2). Then hook the negative pyro battery terminal to ground
+ (Bottom 1) and the positive pyro battery to the pyro battery
+ input (Bottom 2). You can then use the existing pyro screw
+ terminals to hook up all of the pyro charges.
+ </para>
+ </section>
+ <section>
+ <title>Using Only One Battery With EasyMega</title>
+ <para>
+ Because EasyMega has built-in support for a separate pyro
+ battery, if you want to fly with just one battery running
+ both the computer and firing the charges, you need to
+ connect the flight computer battery to the pyro
+ circuit. EasyMega has two screw terminals for this—hook a
+ wire from the Lipo terminal (Bottom 3) to the Pyro terminal
+ (Bottom 2).
+ </para>
+ </section>
+ <section>
+ <title>Using an Active Switch with EasyMega</title>
+ <para>
+ As explained above, an external active switch requires three
+ connections, one to the positive battery terminal, one to
+ the flight computer positive input and one to ground.
+ </para>
+ <para>
+ The positive battery terminal is available on Top terminal
+ 1, the positive flight computer input is on Top terminal
+ 2. Ground is on Top terminal 3.
+ </para>
+ </section>
+ </section>
<section>
<title>Flight Data Recording</title>
<para>
<entry>8MB</entry>
<entry>40</entry>
</row>
+ <row>
+ <entry>EasyMega</entry>
+ <entry>32</entry>
+ <entry>8MB</entry>
+ <entry>40</entry>
+ </row>
</tbody>
</tgroup>
</table>
Configuration data is also stored in the flash memory on
TeleMetrum v1.x, TeleMini and EasyMini. This consumes 64kB
of flash space. This configuration space is not available
- for storing flight log data. TeleMetrum v2.0 and TeleMega
+ for storing flight log data. TeleMetrum v2.0, TeleMega and EasyMega
store configuration data in a bit of eeprom available within
the processor chip, leaving that space available in flash for
more flight data.
The AltOS firmware build for the altimeters has two
fundamental modes, “idle” and “flight”. Which of these modes
the firmware operates in is determined at start up time. For
- TeleMetrum and TeleMega, which have accelerometers, the mode is
+ TeleMetrum, TeleMega and EasyMega, which have accelerometers, the mode is
controlled by the orientation of the
rocket (well, actually the board, of course...) at the time
power is switched on. If the rocket is “nose up”, then
and beep out the maximum height until turned off.
</para>
<para>
- One “neat trick” of particular value when TeleMetrum or TeleMega are used with
+ One “neat trick” of particular value when TeleMetrum, TeleMega
+ or EasyMega are used with
very large air-frames, is that you can power the board up while the
rocket is horizontal, such that it comes up in idle mode. Then you can
raise the air-frame to launch position, and issue a 'reset' command
isn't displaying position information, it's possible that this
is the cause.
</para>
+ <para>
+ APRS packets include an SSID (Secondary Station Identifier)
+ field that allows one operator to have multiple
+ transmitters. AltOS allows you to set this to a single digit
+ from 0 to 9, allowing you to fly multiple transmitters at the
+ same time while keeping the identify of each one separate in
+ the receiver. By default, the SSID is set to the last digit of
+ the device serial number.
+ </para>
<para>
The APRS packet format includes a comment field that can have
arbitrary text in it. AltOS uses this to send status
<entry>M3.7</entry>
<entry>Main Igniter Voltage</entry>
</row>
+ <row>
+ <entry>6</entry>
+ <entry>1286</entry>
+ <entry>Device Serial Number</entry>
+ </row>
</tbody>
</tgroup>
</table>
<para>
Here's an example of an APRS comment showing GPS lock with 6
satellites in view, a primary battery at 4.0V, and
- apogee and main igniters both at 3.7V.
+ apogee and main igniters both at 3.7V from device 1286.
<screen>
- L6 B4.0 A3.7 M3.7
+ L6 B4.0 A3.7 M3.7 1286
</screen>
</para>
<para>
mode.
</para>
</section>
+ <section>
+ <title>Telemetry baud rate</title>
+ <para>
+ This sets the modulation bit rate for data transmission for
+ both telemetry and packet link mode. Lower bit
+ rates will increase range while reducing the amount of data
+ that can be sent and increasing battery consumption. All
+ telemetry is done using a rate 1/2 constraint 4 convolution
+ code, so the actual data transmission rate is 1/2 of the
+ modulation bit rate specified here.
+ </para>
+ </section>
<section>
<title>APRS Interval</title>
<para>
recommend sending packets no more than once every 5 seconds.
</para>
</section>
+ <section>
+ <title>APRS SSID</title>
+ <para>
+ This selects the SSID reported in APRS packets. By default,
+ it is set to the last digit of the serial number, but you
+ can change this to any value from 0 to 9.
+ </para>
+ </section>
<section>
<title>Apogee Delay</title>
<para>
<section>
<title>Pad Orientation</title>
<para>
- TeleMetrum and TeleMega measure acceleration along the axis
+ TeleMetrum, TeleMega and EasyMega measure acceleration along the axis
of the board. Which way the board is oriented affects the
sign of the acceleration value. Instead of trying to guess
which way the board is mounted in the air frame, the
<title>Configurable Pyro Channels</title>
<para>
In addition to the usual Apogee and Main pyro channels,
- TeleMega has four additional channels that can be configured
+ TeleMega and EasyMega have four additional channels that can be configured
to activate when various flight conditions are
satisfied. You can select as many conditions as necessary;
all of them must be met in order to activate the
</listitem>
<listitem>
<para>
- Orientation. TeleMega contains a 3-axis gyroscope and
+ Orientation. TeleMega and EasyMega contain a 3-axis gyroscope and
accelerometer which is used to measure the current
angle. Note that this angle is not the change in angle
from the launch pad, but rather absolute relative to
at all.
</para>
</section>
+ <section>
+ <title>Telemetry baud rate</title>
+ <para>
+ This sets the modulation bit rate for data transmission for
+ both telemetry and packet link mode. Lower bit
+ rates will increase range while reducing the amount of data
+ that can be sent and increasing battery consumption. All
+ telemetry is done using a rate 1/2 constraint 4 convolution
+ code, so the actual data transmission rate is 1/2 of the
+ modulation bit rate specified here.
+ </para>
+ </section>
<section>
<title>APRS Interval</title>
<para>
sending any other telemetry during that time.
</para>
</section>
+ <section>
+ <title>APRS SSID</title>
+ <para>
+ Which SSID to report in APRS packets. By default, this is
+ set to the last digit of the serial number, but can be
+ configured to any value from 0 to 9.
+ </para>
+ </section>
<section>
<title>Callsign</title>
<para>
<section>
<title>Pad Orientation</title>
<para>
- Because they include accelerometers, TeleMetrum and
- TeleMega are sensitive to the orientation of the board. By
+ Because they include accelerometers, TeleMetrum,
+ TeleMega and EasyMega are sensitive to the orientation of the board. By
default, they expect the antenna end to point forward. This
parameter allows that default to be changed, permitting the
board to be mounted with the antenna pointing aft instead.
</informalfigure>
<para>
This opens a separate window to configure the additional
- pyro channels available on TeleMega. One column is
+ pyro channels available on TeleMega and EasyMega. One column is
presented for each channel. Each row represents a single
parameter, if enabled the parameter must meet the specified
test for the pyro channel to be fired. See the Pyro Channels
</mediaobject>
</informalfigure>
<para>
- Select this button and then select a TeleDongle Device from the list provided.
+ Select this button and then select a TeleDongle or TeleBT Device from the list provided.
</para>
<para>
The first few lines of the dialog provide information about the
individual configuration entries.
</para>
<para>
- Note that the TeleDongle itself doesn't save any configuration
+ Note that TeleDongle and TeleBT don't save any configuration
data, the settings here are recorded on the local machine in
- the Java preferences database. Moving the TeleDongle to
+ the Java preferences database. Moving the device to
another machine, or using a different user account on the same
machine will cause settings made here to have no effect.
</para>
</para>
</section>
<section>
- <title>Radio Calibration</title>
+ <title>RF Calibration</title>
<para>
The radios in every Altus Metrum device are calibrated at the
factory to ensure that they transmit and receive on the
- specified frequency. To change a TeleDongle's calibration,
+ specified frequency. To change a TeleDongle or TeleBT's calibration,
you must reprogram the unit completely, so this entry simply
shows the current value and doesn't allow any changes.
</para>
</section>
+ <section>
+ <title>Telemetry Rate</title>
+ <para>
+ This lets you match the telemetry and packet link rate from
+ the transmitter. If they don't match, the device won't
+ receive any data.
+ </para>
+ </section>
</section>
<section>
<title>Flash Image</title>
This reprograms Altus Metrum devices with new
firmware. TeleMetrum v1.x, TeleDongle, TeleMini and TeleBT are
all reprogrammed by using another similar unit as a
- programming dongle (pair programming). TeleMega, TeleMetrum v2
+ programming dongle (pair programming). TeleMega, EasyMega, TeleMetrum v2
and EasyMini are all programmed directly over their USB ports
(self programming). Please read the directions for flashing
devices in the Updating Device Firmware chapter below.
<para>
This listens for telemetry packets on all of the configured
frequencies, displaying information about each device it
- receives a packet from. You can select which of the three
- telemetry formats should be tried; by default, it only listens
- for the standard telemetry packets used in v1.0 and later
+ receives a packet from. You can select which of the baud rates
+ and telemetry formats should be tried; by default, it only listens
+ at 38400 baud with the standard telemetry format used in v1.0 and later
firmware.
</para>
</section>
In the rocket itself, you just need a flight computer and
a single-cell, 3.7 volt nominal Li-Po rechargeable battery. An
850mAh battery weighs less than a 9V alkaline battery, and will
- run a TeleMetrum or TeleMega for hours.
+ run a TeleMetrum, TeleMega or EasyMega for hours.
A 110mAh battery weighs less than a triple A battery and is a good
- choice for use with TeleMini.
+ choice for use with TeleMini or EasyMini.
</para>
<para>
- By default, we ship flight computers with a simple wire antenna.
+ By default, we ship TeleMini, TeleMetrum and TeleMega flight computers with a simple wire antenna.
If your electronics bay or the air-frame it resides within is made
of carbon fiber, which is opaque to RF signals, you may prefer to
install an SMA connector so that you can run a coaxial cable to an
if the rocket is hiding in sage brush or a tree, or if the last GPS position
doesn't get you close enough because the rocket dropped into a canyon, or
the wind is blowing it across a dry lake bed, or something like that... Keith
- currently uses a Yaesu VX-7R, Bdale has a Baofung UV-5R
- which isn't as nice, but was a whole lot cheaper.
+ currently uses a Yaesu FT1D, Bdale has a Yaesu VX-7R, which
+ is a nicer radio in most ways but doesn't support APRS.
</para>
<para>
So, to recap, on the ground the hardware you'll need includes:
</section>
<section>
<title>Future Plans</title>
- <para>
- We've designed a simple GPS based radio tracker called TeleGPS.
- If all goes well, we hope to introduce this in the first
- half of 2014.
- </para>
<para>
We have designed and prototyped several “companion boards” that
- can attach to the companion connector on TeleMetrum and TeleMega
+ can attach to the companion connector on TeleMetrum,
+ TeleMega and EasyMega
flight computers to collect more data, provide more pyro channels,
and so forth. We do not yet know if or when any of these boards
will be produced in enough quantity to sell. If you have specific
<orderedlist inheritnum='inherit' numeration='arabic'>
<listitem>
<para>
- Make sure accelerometer-equipped products like TeleMetrum and
- TeleMega are aligned precisely along the axis of
+ Make sure accelerometer-equipped products like TeleMetrum,
+ TeleMega and EasyMega are aligned precisely along the axis of
acceleration so that the accelerometer can accurately
capture data during the flight.
</para>
<chapter>
<title>Updating Device Firmware</title>
<para>
- TeleMega, TeleMetrum v2 and EasyMini are all programmed directly
+ TeleMega, TeleMetrum v2, EasyMega and EasyMini are all programmed directly
over their USB connectors (self programming). TeleMetrum v1, TeleMini and
TeleDongle are all programmed by using another device as a
programmer (pair programming). It's important to recognize which
performance slightly.
</para>
<para>
- Self-programmable devices (TeleMega, TeleMetrum v2 and EasyMini)
+ Self-programmable devices (TeleMega, TeleMetrum v2, EasyMega and EasyMini)
are reprogrammed by connecting them to your computer over USB
</para>
<section>
<title>
- Updating TeleMega, TeleMetrum v2 or EasyMini Firmware
+ Updating TeleMega, TeleMetrum v2, EasyMega or EasyMini Firmware
</title>
<orderedlist inheritnum='inherit' numeration='arabic'>
<listitem>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>EasyMega</term>
+ <listitem>
+ <para>
+ Connect pin 6 and pin 1 of the companion connector. Pin 1
+ can be identified by the square pad around it, and then
+ the pins could sequentially across the board. Be very
+ careful to <emphasis>not</emphasis> short pin 8 to
+ anything as that is connected directly to the battery. Pin
+ 7 carries 3.3V and the board will crash if that is
+ connected to pin 1, but shouldn't damage the board.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>TeleMetrum v2</term>
<listitem>
</listitem>
</varlistentry>
</variablelist>
+ <para>
+ Once you've located the right pins:
+ </para>
+ <orderedlist inheritnum='inherit' numeration='arabic'>
+ <listitem>
+ <para>
+ Turn the altimeter power off.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Connect a battery.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Connect the indicated terminals together with a short
+ piece of wire. Take care not to accidentally connect
+ anything else.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Connect USB
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Turn the board power on.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The board should now be visible over USB as 'AltosFlash'
+ and be ready to receive firmware.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Once the board has been powered up, you can remove the
+ piece of wire.
+ </para>
+ </listitem>
+ </orderedlist>
</section>
</section>
<section>
</listitem>
</itemizedlist>
</section>
+ <section>
+ <title>
+ EasyMega Specifications
+ </title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Recording altimeter for model rocketry.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Supports dual deployment and four auxiliary pyro channels
+ (a total of 6 events).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Barometric pressure sensor good to 100k feet MSL.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ 1-axis high-g accelerometer for motor characterization, capable of
+ +/- 102g.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ 9-axis IMU including integrated 3-axis accelerometer,
+ 3-axis gyroscope and 3-axis magnetometer.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ On-board 8 Megabyte non-volatile memory for flight data storage.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ USB interface for battery charging, configuration, and data recovery.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Fully integrated support for Li-Po rechargeable batteries.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Can use either main system Li-Po or optional separate pyro battery
+ to fire e-matches.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ 1.25 x 1.25 inch board designed to fit inside 38mm air-frame coupler tube.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
<section>
<title>
TeleMetrum v2 Specifications
</mediaobject>
</informalfigure>
</section>
+ <section>
+ <title>EasyMega template</title>
+ <para>
+ EasyMega has overall dimensions of 1.250 x 2.250 inches, and
+ the mounting holes are sized for use with 4-40 or M3 screws.
+ </para>
+ <informalfigure>
+ <mediaobject id="EasyMegaTemplate">
+ <imageobject>
+ <imagedata format="SVG" fileref="easymega.svg"
+ scalefit="0" scale="100" align="center" />
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+ </section>
<section>
<title>TeleMetrum template</title>
<para>
<title>Calibration</title>
<para>
There are only two calibrations required for TeleMetrum and
- TeleMega, and only one for TeleDongle, TeleMini and EasyMini.
+ TeleMega, and only one for EasyMega, TeleDongle, TeleMini and EasyMini.
All boards are shipped from the factory pre-calibrated, but
the procedures are documented here in case they are ever
needed. Re-calibration is not supported by AltosUI, you must
</para>
</section>
<section>
- <title>TeleMetrum and TeleMega Accelerometers</title>
+ <title>TeleMetrum, TeleMega and EasyMega Accelerometers</title>
<para>
While barometric sensors are factory-calibrated,
accelerometers are not, and so each must be calibrated once
</para>
<para>
In the unlikely event an accel cal goes badly, it is possible
- that TeleMetrum or TeleMega may always come up in 'pad mode'
+ that TeleMetrum, TeleMega or EasyMega may always come up in 'pad mode'
and as such not be listening to either the USB or radio link.
If that happens, there is a special hook in the firmware to
force the board back in to 'idle mode' so you can re-do the
<appendix>
<title>Release Notes</title>
<simplesect>
- <title>Version 1.41</title>
+ <title>Version 1.4.1</title>
<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="release-notes-1.4.1.xsl"
xpointer="xpointer(/article/*)"/>
</simplesect>
+ <simplesect>
+ <title>Version 1.5</title>
+ <xi:include
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="release-notes-1.5.xsl"
+ xpointer="xpointer(/article/*)"/>
+ </simplesect>
<simplesect>
<title>Version 1.4</title>
<xi:include
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+ "/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
+<article>
+ <title>EasyMega Outline and Hole Pattern</title>
+ <para>
+ This image, when printed, provides a precise template for the
+ mounting holes in EasyMega. EasyMega has overall dimensions
+ of 1.250 x 2.250 inches, and the mounting holes are sized for
+ use with 4-40 or M3 screws.
+ </para>
+ <informalfigure>
+ <mediaobject id="EasyMegaTemplate">
+ <imageobject>
+ <imagedata format="SVG" fileref="easymega.svg"
+ scalefit="0" scale="100" align="center" />
+ </imageobject>
+ </mediaobject>
+ </informalfigure>
+</article>
+
+<!-- LocalWords: Altusmetrum
+-->
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ width="2.5in"
+ height="1.5in"
+ viewBox="0 0 250 150"
+ preserveaspectratio="none"
+ id="svg2"
+ version="1.1">
+ <g transform="translate(12.5,12.5)"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-size:24">
+ <!-- outline -->
+ <rect width="225" height="125" x="0" y="0"/>
+ <!-- holes -->
+ <path d="M12.5,12.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/>
+ <path d="M212.5,12.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/>
+ <path d="M12.5,112.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/>
+ <path d="M212.5,112.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/>
+ <!-- arrow -->
+ <path d="M50,62.5 l125,0"/>
+ <path style="fill:#000000;stroke:none" d="M175,57.5 l10,5 l-10,5 z"/>
+ <!-- label -->
+ <text x="112.5" y="57.5" style="fill:#000000;stroke:none" text-anchor="middle">EasyMega</text>
+ <g transform="rotate(90)">
+ <text x="62.5" y="-190" style="fill:#000000;stroke:none" text-anchor="middle">UP</text>
+ </g>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
+
+<article>
+ <para>
+ Version 1.5 is a major release. It includes support for our new
+ EasyMega product, new features and bug fixes in in the flight
+ software for all our boards and the AltosUI ground station
+ </para>
+ <para>
+ AltOS New Features
+ <itemizedlist>
+ <listitem>
+ <para>
+ Add support for EasyMega boards.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Make the APRS SSID be configurable. This lets you track
+ different rockets on the same receiver without getting
+ things mixed up.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Report extra pyro channel continuity state on EasyMega and
+ TeleMega via the beeper. This lets you easily verify flight
+ readiness on these boards after powering up the electronics
+ on the rail.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Add lower telemetry data rates (2400 and 9600 bps) to
+ increase telemetry radio range. This reduces the amount of
+ data received as well as increasing battery consumption in
+ the transmitter.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Change TeleGPS to have only a single log, and append new
+ data to it rather than using seperate per-flight logs. This
+ avoids accidentally filling up log storage by turning
+ TeleGPS on/off several times.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltOS Fixes
+ <itemizedlist>
+ <listitem>
+ <para>
+ Increase the maximum range for altitude values from +/-32767m
+ to +/-2147483647m, allowing the flight computers to function
+ correctly above the 32km level.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Continuously test pyro firing conditions during delay stage,
+ inhibiting the pyro channel if the test fails. This prevents
+ firing pyro charges where the conditions were good before
+ the delay, but become bad before the delay expires.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Allow negative numbers in pyro configuration values. This
+ lets you specify things like descending speed or
+ deceleration.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltosUI and TeleGPS New Features
+ <itemizedlist>
+ <listitem>
+ <para>
+ Support telemetry baud rate selection. Adds menus to
+ the flight monitoring and configuration for baud rate
+ selection.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Support APRS SSID configuration.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Integrate with file managers. This provides icons for all of
+ our file types and associates our application with the files
+ so that using a file manager to open a AltOS data file
+ results in launching our application.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltosUI Fixes
+ <itemizedlist>
+ <listitem>
+ <para>
+ Make the 'Graph' button on the landed tab work again.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Make tests for Java on Windows a bit smarter, and also
+ provide the user with the option to skip installing Java for
+ cases where we just can't figure out what version is installed.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+</article>
-altus-metrum-*.png
-micropeak-*.png
-telegps-*.png
+application-*.png
+altusmetrum-*.png
+*.rc
*.ico
*.icns
*.build
+*.exe
WIN_RES=16 24 32 48 64 72 96 128 180 256
RES=$(shell echo $(JAVA_RES) $(MAC_RES) $(WIN_RES) | awk '{ for (i = 1; i <= NF; i++) printf("%s\n", $$i); }' | sort -n -u)
-AM_FILES=$(shell for i in $(RES); do echo altus-metrum-$$i.png; done)
-MP_FILES=$(shell for i in $(RES); do echo micropeak-$$i.png; done)
-TG_FILES=$(shell for i in $(RES); do echo telegps-$$i.png; done)
+# Application icon base names
-MAC_TG_FILES=$(shell for i in $(MAC_RES); do echo telegps-$$i.png; done)
-MAC_MP_FILES=$(shell for i in $(MAC_RES); do echo micropeak-$$i.png; done)
-MAC_AM_FILES=$(shell for i in $(MAC_RES); do echo altus-metrum-$$i.png; done)
+AM_NAME = altusmetrum-altosui
+MP_NAME = altusmetrum-micropeak
+TG_NAME = altusmetrum-telegps
-WIN_TG_FILES=$(shell for i in $(WIN_RES); do echo telegps-$$i.png; done)
-WIN_MP_FILES=$(shell for i in $(WIN_RES); do echo micropeak-$$i.png; done)
-WIN_AM_FILES=$(shell for i in $(WIN_RES); do echo altus-metrum-$$i.png; done)
+# File icon base names
-ICO_FILES=altus-metrum.ico micro-peak.ico telegps.ico
-ICNS_FILES=AltosUIIcon.icns TeleGPS.icns MicroPeak.icns
+EEPROM_NAME = application-vnd.altusmetrum.eeprom
+TELEM_NAME = application-vnd.altusmetrum.telemetry
+MPD_NAME = application-vnd.altusmetrum.micropeak
-icondir = $(datadir)/icons/hicolor/scalable/apps
+# Application icons
-AM_ICON = altusmetrum.svg
-MP_ICON = micropeak.svg
-TG_ICON = telegps.svg
+AM_ICON = $(AM_NAME).svg
+MP_ICON = $(MP_NAME).svg
+TG_ICON = $(TG_NAME).svg
-icon_DATA = $(AM_ICON) $(MP_ICON) $(TG_ICON)
+# File icons (note that MicroPeak uses the application icon for files)
-EXTRA_DIST = $(icon_DATA) $(AM_FILES) $(MP_FILES) $(TG_FILES)
+EEPROM_ICON = $(EEPROM_NAME).svg
+TELEM_ICON = $(TELEM_NAME).svg
+MPD_ICON = $(MPD_NAME).svg
+
+# Files needed for Mac OSX icons
+
+MAC_AM_FILES = $(shell for i in $(MAC_RES); do echo $(AM_NAME)-$$i.png; done)
+MAC_MP_FILES = $(shell for i in $(MAC_RES); do echo $(MP_NAME)-$$i.png; done)
+MAC_TG_FILES = $(shell for i in $(MAC_RES); do echo $(TG_NAME)-$$i.png; done)
+MAC_EEPROM_FILES= $(shell for i in $(MAC_RES); do echo $(EEPROM_NAME)-$$i.png; done)
+MAC_TELEM_FILES = $(shell for i in $(MAC_RES); do echo $(TELEM_NAME)-$$i.png; done)
+MAC_MPD_FILES = $(shell for i in $(MAC_RES); do echo $(MPD_NAME)-$$i.png; done)
+
+ICNS_FILES = $(AM_NAME).icns $(MP_NAME).icns $(TG_NAME).icns \
+ $(EEPROM_NAME).icns $(TELEM_NAME).icns $(MPD_NAME).icns
+
+# Files needed for Windows icons
+
+WIN_AM_FILES = $(shell for i in $(WIN_RES); do echo $(AM_NAME)-$$i.png; done)
+WIN_MP_FILES = $(shell for i in $(WIN_RES); do echo $(MP_NAME)-$$i.png; done)
+WIN_TG_FILES = $(shell for i in $(WIN_RES); do echo $(TG_NAME)-$$i.png; done)
+WIN_EEPROM_FILES= $(shell for i in $(WIN_RES); do echo $(EEPROM_NAME)-$$i.png; done)
+WIN_TELEM_FILES = $(shell for i in $(WIN_RES); do echo $(TELEM_NAME)-$$i.png; done)
+WIN_MPD_FILES = $(shell for i in $(WIN_RES); do echo $(MPD_NAME)-$$i.png; done)
+
+ICO_FILES = $(AM_NAME).ico $(MP_NAME).ico $(TG_NAME).ico \
+ $(EEPROM_NAME).ico $(TELEM_NAME).ico $(MPD_NAME).ico
+
+EXE_FILES = $(AM_NAME).exe $(MP_NAME).exe $(TG_NAME).exe \
+ $(EEPROM_NAME).exe $(TELEM_NAME).exe $(MPD_NAME).exe
+
+# Files needed for Java internal icons
+
+JAVA_AM_FILES = $(shell for i in $(JAVA_RES); do echo $(AM_NAME)-$$i.png; done)
+JAVA_MP_FILES = $(shell for i in $(JAVA_RES); do echo $(MP_NAME)-$$i.png; done)
+JAVA_TG_FILES = $(shell for i in $(JAVA_RES); do echo $(TG_NAME)-$$i.png; done)
+
+JAVA_FILES = $(JAVA_AM_FILES) $(JAVA_MP_FILES) $(JAVA_TG_FILES)
+
+# PNG files needed by anyone
+
+AM_FILES = $(shell for i in $(RES); do echo $(AM_NAME)-$$i.png; done)
+MP_FILES = $(shell for i in $(RES); do echo $(MP_NAME)-$$i.png; done)
+TG_FILES = $(shell for i in $(RES); do echo $(TG_NAME)-$$i.png; done)
+EEPROM_FILES = $(shell for i in $(RES); do echo $(EEPROM_NAME)-$$i.png; done)
+TELEM_FILES = $(shell for i in $(RES); do echo $(TELEM_NAME)-$$i.png; done)
+IN_MPD_FILES = $(shell for i in $(RES); do echo $(MPD_NAME)-$$i.png; done)
+
+# XPM file needed by debian
+
+AM_XPM = altusmetrum.xpm
+
+ICON_THEME=$(datadir)/icons/hicolor
+
+appicondir = $(ICON_THEME)/scalable/apps
+appicon_DATA = $(AM_ICON) $(MP_ICON) $(TG_ICON)
+
+MIME_ICONS = $(EEPROM_ICON) $(TELEM_ICON) $(MPD_ICON)
+
+mimeicondir = $(ICON_THEME)/scalable/mimetypes
+mimeicon_DATA = $(MIME_ICONS)
+
+mimedir = $(datadir)/mime/packages
+mime_DATA = org-altusmetrum-mimetypes.xml
+
+pixmapdir = $(datadir)/pixmaps
+pixmap_DATA = altusmetrum.xpm
+
+EXTRA_DIST = $(appicon_DATA) $(mimeicon_DATA) $(mime_DATA) windows-stub.c
res:
echo $(RES)
-all-local: $(ICO_FILES) $(ICNS_FILES)
+java-altosui:
+ @echo $(JAVA_AM_FILES)
+
+java-micropeak:
+ @echo $(JAVA_MP_FILES)
+
+java-telegps:
+ @echo $(JAVA_TG_FILES)
+
+fat: all $(ICO_FILES) $(ICNS_FILES) $(EXE_FILES)
+
+all-local: $(JAVA_FILES) $(AM_XPM)
clean-local:
- $(RM) altus-metrum-*.png telegps-*.png micropeak-*.png *.build *.ico *.icns
+ $(RM) $(AM_NAME)-*.png $(TG_NAME)-*.png $(MP_NAME)-*.png
+ $(RM) altus-metrum-*.png micropeak-*.png telegps-*.png
+ $(RM) $(EEPROM_NAME)-*.png $(TELEM_NAME)-*.png $(MPD_NAME)-*.png
+ $(RM) *.build *.ico *.rc *.icns *.o *.exe $(MPD_ICON)
+ $(RM) altusmetrum.xpm
+
+install-data-hook:
+ update-mime-database $(datadir)/mime
+ update-icon-caches $(ICON_THEME)
-$(AM_FILES): altusmetrum.build
+$(MPD_ICON): $(MP_ICON)
+ $(LN_S) $(MP_ICON) $@
-altusmetrum.build: altusmetrum.svg
- for i in $(RES); do rsvg-convert -w $$i -h $$i -o altus-metrum-$$i.png altusmetrum.svg; done && touch $@
+XPM_SRC=altusmetrum-altosui-32.png
-$(TG_FILES): telegps.build
+altusmetrum.xpm: $(XPM_SRC)
+ pngtopnm -alpha $(XPM_SRC) > mask-$@ && \
+ pngtopnm $(XPM_SRC) | \
+ ppmtoxpm -alphamask=mask-$@ > $@ && rm mask-$@
-telegps.build: telegps.svg
- for i in $(RES); do rsvg-convert -w $$i -h $$i -o telegps-$$i.png telegps.svg; done && touch $@
+$(AM_FILES): $(AM_NAME).build
+$(MP_FILES): $(MP_NAME).build
+$(TG_FILES): $(TG_NAME).build
-$(MP_FILES): micropeak.build
+SUFFIXES=.svg .build .icns .ico .rc .o .exe
-micropeak.build: micropeak.svg
- for i in $(RES); do rsvg-convert -w $$i -h $$i -o micropeak-$$i.png micropeak.svg; done && touch $@
+.svg.build:
+ for i in $(RES); do rsvg-convert -w $$i -h $$i -o $*-$$i.png $*.svg; done && touch $@
-#clean-local:
-# $(RM) -f $(ICO_FILES)
+.build.icns:
+ png2icns $@ $(shell for i in $(MAC_RES); do echo $*-$$i.png; done)
-altus-metrum.ico: $(WIN_AM_FILES)
- icotool -c -o $@ $(WIN_AM_FILES)
+.build.ico:
+ icotool -c -o $@ $(shell for i in $(WIN_RES); do echo $*-$$i.png; done)
-micro-peak.ico: $(WIN_MP_FILES)
- icotool -c -o $@ $(WIN_MP_FILES)
+.ico.rc:
+ echo '101 ICON "$*.ico"' > $@
-telegps.ico: $(WIN_TG_FILES)
- icotool -c -o $@ $(WIN_TG_FILES)
-AltosUIIcon.icns: $(MAC_AM_FILES)
- png2icns $@ $(MAC_AM_FILES)
+MINGCC32=i686-w64-mingw32-gcc
+MINGWINDRES=i686-w64-mingw32-windres
-TeleGPS.icns: $(MAC_TG_FILES)
- png2icns $@ $(MAC_TG_FILES)
+.rc.o:
+ $(MINGWINDRES) $*.rc $@
-MicroPeak.icns: $(MAC_MP_FILES)
- png2icns $@ $(MAC_MP_FILES)
+.o.exe:
+ $(MINGCC32) -o $@ windows-stub.c $*.o
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ width="214.27165"
+ height="266.00192"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="altusmetrum.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
+ inkscape:export-xdpi="119.89881"
+ inkscape:export-ydpi="119.89881">
+ <metadata
+ id="metadata14">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs12">
+ <linearGradient
+ id="linearGradient3165">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3167" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3169" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3177">
+ <stop
+ style="stop-color:#da7000;stop-opacity:1;"
+ offset="0"
+ id="stop3179" />
+ <stop
+ id="stop3447"
+ offset="0.24528302"
+ style="stop-color:#a63852;stop-opacity:1;" />
+ <stop
+ style="stop-color:#7200a4;stop-opacity:1;"
+ offset="1"
+ id="stop3181" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3169">
+ <stop
+ style="stop-color:#ff8a00;stop-opacity:1;"
+ offset="0"
+ id="stop3171" />
+ <stop
+ id="stop3445"
+ offset="0.71698111"
+ style="stop-color:#c24573;stop-opacity:0.98039216;" />
+ <stop
+ style="stop-color:#8500e7;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3173" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 121 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="191 : 121 : 1"
+ inkscape:persp3d-origin="95.5 : 80.666667 : 1"
+ id="perspective16" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3175"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3171"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3020"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3022"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3024"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3026"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3028"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3030"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <filter
+ id="filter3005"
+ inkscape:label="Drop Shadow"
+ color-interpolation-filters="sRGB">
+ <feFlood
+ id="feFlood3007"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite3009"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur3011"
+ stdDeviation="80"
+ result="blur" />
+ <feOffset
+ id="feOffset3013"
+ dx="100"
+ dy="100"
+ result="offset" />
+ <feComposite
+ id="feComposite3015"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ inkscape:cy="128.91168"
+ inkscape:cx="271.89232"
+ inkscape:zoom="2.4559706"
+ inkscape:window-height="1177"
+ inkscape:window-width="1462"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:window-x="266"
+ inkscape:window-y="43"
+ inkscape:current-layer="svg2"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="20"
+ fit-margin-bottom="20" />
+ <g
+ transform="matrix(0.1,0,0,0.1,1.967113,2.4742836)"
+ id="g3"
+ style="fill:url(#radialGradient3175);fill-opacity:1;stroke:url(#radialGradient3171);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;filter:url(#filter3005)">
+ <g
+ transform="translate(20.61545,-27.69425)"
+ style="fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3030);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+ id="g5">
+ <path
+ d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z"
+ id="path7"
+ style="fill:url(#radialGradient3020);fill-opacity:1;stroke:url(#radialGradient3022);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z"
+ id="path9"
+ style="fill:url(#radialGradient3024);fill-opacity:1;stroke:url(#radialGradient3026);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="49.03825"
+ height="43.606411"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="micropeak.svg">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient5343">
+ <stop
+ style="stop-color:#7200a4;stop-opacity:1;"
+ offset="0"
+ id="stop5345" />
+ <stop
+ style="stop-color:#da7000;stop-opacity:1;"
+ offset="1"
+ id="stop5347" />
+ </linearGradient>
+ <marker
+ inkscape:stockid="Arrow2Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Send"
+ style="overflow:visible">
+ <path
+ id="path3798"
+ style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-0.3,0,0,-0.3,0.69,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Send"
+ style="overflow:visible">
+ <path
+ id="path3780"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path3792"
+ style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6,-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3768"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3786"
+ style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5343"
+ id="linearGradient5349"
+ x1="255.48561"
+ y1="275.90405"
+ x2="280.61411"
+ y2="275.90405"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ id="filter3027"
+ inkscape:label="Drop Shadow"
+ color-interpolation-filters="sRGB">
+ <feFlood
+ id="feFlood3029"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite3031"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur3033"
+ stdDeviation="1.6"
+ result="blur" />
+ <feOffset
+ id="feOffset3035"
+ dx="2"
+ dy="2"
+ result="offset" />
+ <feComposite
+ id="feComposite3037"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="8.160856"
+ inkscape:cx="33.152671"
+ inkscape:cy="27.859227"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1277"
+ inkscape:window-height="894"
+ inkscape:window-x="543"
+ inkscape:window-y="242"
+ inkscape:window-maximized="0"
+ fit-margin-top="-3"
+ fit-margin-left="-4"
+ fit-margin-right="-1"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-241.43522,-252.43073)">
+ <g
+ id="g3000"
+ style="filter:url(#filter3027)">
+ <g
+ id="text2985"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#7200a4;fill-opacity:1;stroke:none;font-family:Minion Pro;-inkscape-font-specification:Minion Pro">
+ <path
+ inkscape:connector-curvature="0"
+ id="path3003"
+ style="font-size:36px;font-weight:500;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#7200a4;font-family:ITC Benguiat Gothic Std;-inkscape-font-specification:ITC Benguiat Gothic Std Medium"
+ d="m 257.20241,268.30647 c 0,-1.07999 -0.396,-1.872 -1.584,-1.872 -1.188,0 -1.584,0.79201 -1.584,1.872 l 0,8.676 c 0,2.88 -2.052,5.112 -4.824,5.112 -3.06,0 -4.104,-1.872 -4.104,-5.076 l 0,-8.712 c 0,-1.07999 -0.396,-1.872 -1.584,-1.872 -1.188,0 -1.584,0.79201 -1.584,1.872 l 0,21.924 c 0,1.08 0.396,1.872 1.584,1.872 1.188,0 1.584,-0.792 1.584,-1.872 l 0,-6.156 c 0.792,0.612 2.088,0.972 3.564,0.972 2.304,0 4.428,-0.792 5.652,-2.988 l 0.072,0.072 0,1.26 c 0,0.864 0.54,1.44 1.404,1.44 0.864,0 1.404,-0.576 1.404,-1.44 l 0,-15.084" />
+ </g>
+ <path
+ sodipodi:nodetypes="cssc"
+ inkscape:connector-curvature="0"
+ id="path2991"
+ d="m 256.93561,290.70327 c 3.04022,-0.24413 4.30317,-2.66932 5.38268,-5.56604 1.68059,-4.50963 3.67214,-15.86904 8.62227,-20.55527 4.0668,-3.85 8.22354,-3.46656 8.22354,-3.46656"
+ style="fill:none;stroke:url(#linearGradient5349);stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:none" />
+ <path
+ inkscape:transform-center-y="-0.40889198"
+ inkscape:transform-center-x="-0.29194889"
+ d="m 282.7522,267.42614 -3.93403,-2.77705 -4.51792,1.66641 1.42544,-4.59964 -2.98096,-3.78185 4.815,-0.0657 2.67559,-4.00372 1.55039,4.55904 4.63457,1.30742 -3.85681,2.88333 z"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ inkscape:flatsided="false"
+ sodipodi:arg2="1.7014539"
+ sodipodi:arg1="1.0731354"
+ sodipodi:r2="3.6257365"
+ sodipodi:r1="7.2514729"
+ sodipodi:cy="261.05426"
+ sodipodi:cx="279.29056"
+ sodipodi:sides="5"
+ id="path5341"
+ style="fill:none;stroke:#da7000;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:type="star" />
+ </g>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="151.43401"
+ height="144.50209"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="telegps.svg">
+ <defs
+ id="defs4">
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3175"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3169">
+ <stop
+ style="stop-color:#ff8a00;stop-opacity:1;"
+ offset="0"
+ id="stop3171" />
+ <stop
+ id="stop3445"
+ offset="0.71698111"
+ style="stop-color:#c24573;stop-opacity:0.98039216;" />
+ <stop
+ style="stop-color:#8500e7;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3173" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3171"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3165">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3167" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3169" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient2838"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <linearGradient
+ id="linearGradient3181">
+ <stop
+ style="stop-color:#ff8a00;stop-opacity:1;"
+ offset="0"
+ id="stop3183" />
+ <stop
+ id="stop3185"
+ offset="0.71698111"
+ style="stop-color:#c24573;stop-opacity:0.98039216;" />
+ <stop
+ style="stop-color:#8500e7;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3187" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient2840"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <linearGradient
+ id="linearGradient3190">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3192" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3194" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient2830"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <linearGradient
+ id="linearGradient3197">
+ <stop
+ style="stop-color:#ff8a00;stop-opacity:1;"
+ offset="0"
+ id="stop3199" />
+ <stop
+ id="stop3201"
+ offset="0.71698111"
+ style="stop-color:#c24573;stop-opacity:0.98039216;" />
+ <stop
+ style="stop-color:#8500e7;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3203" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient2832"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <linearGradient
+ id="linearGradient3206">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3208" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3210" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient2834"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <linearGradient
+ id="linearGradient3213">
+ <stop
+ style="stop-color:#ff8a00;stop-opacity:1;"
+ offset="0"
+ id="stop3215" />
+ <stop
+ id="stop3217"
+ offset="0.71698111"
+ style="stop-color:#c24573;stop-opacity:0.98039216;" />
+ <stop
+ style="stop-color:#8500e7;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3219" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient2836"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <linearGradient
+ id="linearGradient3222">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3224" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3226" />
+ </linearGradient>
+ <radialGradient
+ r="951.68701"
+ fy="2305.2668"
+ fx="951.68713"
+ cy="2305.2668"
+ cx="951.68713"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3232"
+ xlink:href="#linearGradient3169"
+ inkscape:collect="always" />
+ <radialGradient
+ r="951.68701"
+ fy="1205.2668"
+ fx="951.68713"
+ cy="1205.2668"
+ cx="951.68713"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3234"
+ xlink:href="#linearGradient3165"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient4101"
+ cx="194.54575"
+ cy="361.16367"
+ fx="194.54575"
+ fy="361.16367"
+ r="70.597672"
+ gradientTransform="matrix(1,0,0,0.95908583,137.14286,74.776711)"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ id="filter3238"
+ inkscape:label="Drop Shadow"
+ color-interpolation-filters="sRGB">
+ <feFlood
+ id="feFlood3240"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite3242"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur3244"
+ stdDeviation="4"
+ result="blur" />
+ <feOffset
+ id="feOffset3246"
+ dx="5"
+ dy="5"
+ result="offset" />
+ <feComposite
+ id="feComposite3248"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="3.959798"
+ inkscape:cx="91.754359"
+ inkscape:cy="68.172898"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="-12"
+ fit-margin-left="-12"
+ fit-margin-right="-6"
+ fit-margin-bottom="-6"
+ inkscape:window-width="996"
+ inkscape:window-height="970"
+ inkscape:window-x="930"
+ inkscape:window-y="553"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-258.97144,-351.91262)">
+ <path
+ style="fill:url(#radialGradient4101);fill-opacity:1;filter:url(#filter3238)"
+ d="m 261.09094,466.61035 1.9122,-1.69399 39.0721,-36.4688 20.74158,22.05252 -40.71991,38.37279 z m 36.24983,1.34654 -14.08636,-15.38433 -15.33887,14.40857 14.50759,15.23741 z m 18.98704,-17.58715 -14.47613,-15.53942 -14.95191,14.42099 14.19976,15.37575 z m 43.2565,3.24033 -5.69326,-6.00917 -2.76929,1.85727 c -5.01515,3.36349 -10.61773,4.75193 -13.55344,3.35884 -0.90785,-0.4308 -11.20677,-10.85557 -16.46128,-16.61505 -6.3177,-6.92484 -17.77225,-18.68338 -18.08204,-21.53696 l -0.25491,-2.34789 -6.68224,-3.00173 -6.68224,-3.00173 -0.12416,-2.54849 c -0.24316,-4.99109 2.61694,-11.66135 7.10652,-16.57368 6.51922,-7.13306 14.23173,-10.81215 21.4071,-10.21178 l 2.49577,0.20881 2.34108,7.3087 2.34109,7.3087 2.0542,0.21626 c 1.12981,0.11895 2.29245,0.36702 2.58364,0.55127 0.29119,0.18424 11.17756,11.55849 16.63562,17.46044 5.67391,6.13537 16.35301,17.71615 16.74619,18.65715 1.36492,3.26672 -0.56522,9.34479 -4.44838,14.00803 -0.92939,1.1161 -1.6875,2.14976 -1.6847,2.29703 0.003,0.14726 2.44601,2.88431 5.42933,6.08233 2.98332,3.19801 5.42421,6.02814 5.42421,6.28919 0,0.66794 -0.91528,1.72591 -1.73982,2.01104 -0.50334,0.17406 -2.27007,-1.42112 -6.38899,-5.76858 z m -13.8944,-6.52384 c 0.96195,-0.49074 2.46683,-1.3673 3.34417,-1.94791 l 1.59519,-1.05564 -1.69025,-1.72225 c -1.71532,-1.74777 -2.09589,-2.99732 -1.1891,-3.90412 0.98407,-0.98406 2.33559,-0.53387 3.9423,1.31314 l 1.57825,1.81431 1.43638,-1.7099 c 1.7115,-2.03742 3.3933,-5.47555 3.39008,-6.9304 -0.0104,-4.68327 -7.01613,-2.68794 -13.36898,3.80766 -4.26282,4.35861 -6.32786,9.57528 -4.26584,10.77629 1.19252,0.69458 3.36009,0.51166 5.2278,-0.44118 z m -37.53066,-44.39022 c 2.23934,-2.70633 7.29399,-6.99375 10.13666,-8.59806 1.69887,-0.95877 2.21231,-1.46174 2.04152,-1.99985 -0.1255,-0.3954 -1.05734,-3.0661 -2.07077,-5.93487 l -1.84259,-5.21596 -1.60649,0.12825 c -4.1301,0.32972 -9.06228,2.86043 -13.29918,6.82384 -4.03277,3.77245 -7.7843,10.20829 -7.89014,13.53572 l -0.0463,1.4539 5.4085,2.47197 5.4085,2.47197 1.02919,-1.54008 c 0.56606,-0.84704 1.79503,-2.46562 2.73105,-3.59683 z m 32.91039,-10.47213 40.55794,-38.76942 c 7.09795,7.71166 14.5366,15.63755 20.65837,22.2503 l -40.53088,38.2414 z m 35.73645,1.02093 -14.2595,-15.3791 -15.29495,14.35785 14.65467,15.14661 z m 18.6801,-17.55816 -14.10162,-15.40128 -15.32812,14.3973 14.52992,15.24342 z"
+ id="path3063"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccscssascccssscccscasscsssssccssscssssscssscssccccsccccccccccccccccc" />
+ </g>
+</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- id="svg2"
- width="214.27165"
- height="266.00192"
- version="1.0"
- sodipodi:version="0.32"
- inkscape:version="0.48.4 r9939"
- sodipodi:docname="altusmetrum.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
- inkscape:export-xdpi="119.89881"
- inkscape:export-ydpi="119.89881">
- <metadata
- id="metadata14">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs12">
- <linearGradient
- id="linearGradient3165">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop3167" />
- <stop
- style="stop-color:#000000;stop-opacity:0;"
- offset="1"
- id="stop3169" />
- </linearGradient>
- <linearGradient
- id="linearGradient3177">
- <stop
- style="stop-color:#da7000;stop-opacity:1;"
- offset="0"
- id="stop3179" />
- <stop
- id="stop3447"
- offset="0.24528302"
- style="stop-color:#a63852;stop-opacity:1;" />
- <stop
- style="stop-color:#7200a4;stop-opacity:1;"
- offset="1"
- id="stop3181" />
- </linearGradient>
- <linearGradient
- id="linearGradient3169">
- <stop
- style="stop-color:#ff8a00;stop-opacity:1;"
- offset="0"
- id="stop3171" />
- <stop
- id="stop3445"
- offset="0.71698111"
- style="stop-color:#c24573;stop-opacity:0.98039216;" />
- <stop
- style="stop-color:#8500e7;stop-opacity:0.96078432;"
- offset="1"
- id="stop3173" />
- </linearGradient>
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 121 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="191 : 121 : 1"
- inkscape:persp3d-origin="95.5 : 80.666667 : 1"
- id="perspective16" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient3175"
- cx="951.68713"
- cy="2305.2668"
- fx="951.68713"
- fy="2305.2668"
- r="951.68701"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient3171"
- cx="951.68713"
- cy="1205.2668"
- fx="951.68713"
- fy="1205.2668"
- r="951.68701"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient3020"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="2305.2668"
- fx="951.68713"
- fy="2305.2668"
- r="951.68701" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient3022"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="1205.2668"
- fx="951.68713"
- fy="1205.2668"
- r="951.68701" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient3024"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="2305.2668"
- fx="951.68713"
- fy="2305.2668"
- r="951.68701" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient3026"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="1205.2668"
- fx="951.68713"
- fy="1205.2668"
- r="951.68701" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient3028"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="2305.2668"
- fx="951.68713"
- fy="2305.2668"
- r="951.68701" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient3030"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="1205.2668"
- fx="951.68713"
- fy="1205.2668"
- r="951.68701" />
- <filter
- id="filter3005"
- inkscape:label="Drop Shadow"
- color-interpolation-filters="sRGB">
- <feFlood
- id="feFlood3007"
- flood-opacity="0.604"
- flood-color="rgb(0,0,0)"
- result="flood" />
- <feComposite
- id="feComposite3009"
- in2="SourceGraphic"
- in="flood"
- operator="in"
- result="composite1" />
- <feGaussianBlur
- id="feGaussianBlur3011"
- stdDeviation="80"
- result="blur" />
- <feOffset
- id="feOffset3013"
- dx="100"
- dy="100"
- result="offset" />
- <feComposite
- id="feComposite3015"
- in2="offset"
- in="SourceGraphic"
- operator="over"
- result="composite2" />
- </filter>
- </defs>
- <sodipodi:namedview
- inkscape:cy="128.91168"
- inkscape:cx="271.89232"
- inkscape:zoom="2.4559706"
- inkscape:window-height="1177"
- inkscape:window-width="1462"
- inkscape:pageshadow="2"
- inkscape:pageopacity="0.0"
- guidetolerance="10.0"
- gridtolerance="10.0"
- objecttolerance="10.0"
- borderopacity="1.0"
- bordercolor="#666666"
- pagecolor="#ffffff"
- id="base"
- showgrid="false"
- inkscape:window-x="266"
- inkscape:window-y="43"
- inkscape:current-layer="svg2"
- inkscape:window-maximized="0"
- fit-margin-top="0"
- fit-margin-left="0"
- fit-margin-right="20"
- fit-margin-bottom="20" />
- <g
- transform="matrix(0.1,0,0,0.1,1.967113,2.4742836)"
- id="g3"
- style="fill:url(#radialGradient3175);fill-opacity:1;stroke:url(#radialGradient3171);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;filter:url(#filter3005)">
- <g
- transform="translate(20.61545,-27.69425)"
- style="fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3030);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
- id="g5">
- <path
- d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z"
- id="path7"
- style="fill:url(#radialGradient3020);fill-opacity:1;stroke:url(#radialGradient3022);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z"
- id="path9"
- style="fill:url(#radialGradient3024);fill-opacity:1;stroke:url(#radialGradient3026);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- </g>
- </g>
-</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ width="214.27165"
+ height="266.00192"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="application-vnd-altusmetrum-eeprom.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
+ inkscape:export-xdpi="119.89881"
+ inkscape:export-ydpi="119.89881">
+ <metadata
+ id="metadata14">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs12">
+ <linearGradient
+ id="linearGradient3165">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3167" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3169" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3177">
+ <stop
+ style="stop-color:#da7000;stop-opacity:1;"
+ offset="0"
+ id="stop3179" />
+ <stop
+ id="stop3447"
+ offset="0.24528302"
+ style="stop-color:#a63852;stop-opacity:1;" />
+ <stop
+ style="stop-color:#7200a4;stop-opacity:1;"
+ offset="1"
+ id="stop3181" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3169">
+ <stop
+ style="stop-color:#ff8a00;stop-opacity:1;"
+ offset="0"
+ id="stop3171" />
+ <stop
+ id="stop3445"
+ offset="0.71698111"
+ style="stop-color:#c24573;stop-opacity:0.98039216;" />
+ <stop
+ style="stop-color:#8500e7;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3173" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 121 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="191 : 121 : 1"
+ inkscape:persp3d-origin="95.5 : 80.666667 : 1"
+ id="perspective16" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3175"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3171"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3020"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3022"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3024"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3026"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3028"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3030"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <filter
+ id="filter3005"
+ inkscape:label="Drop Shadow"
+ color-interpolation-filters="sRGB">
+ <feFlood
+ id="feFlood3007"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite3009"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur3011"
+ stdDeviation="80"
+ result="blur" />
+ <feOffset
+ id="feOffset3013"
+ dx="100"
+ dy="100"
+ result="offset" />
+ <feComposite
+ id="feComposite3015"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient4415"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient4417"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient4419"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient4421"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient4423"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient4425"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient4427"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient4429"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <filter
+ id="filter4485"
+ style="color-interpolation-filters:sRGB;"
+ inkscape:label="Drop Shadow">
+ <feFlood
+ id="feFlood4487"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite4489"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur4491"
+ in="composite"
+ stdDeviation="8"
+ result="blur" />
+ <feOffset
+ id="feOffset4493"
+ dx="10"
+ dy="10"
+ result="offset" />
+ <feComposite
+ id="feComposite4495"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ inkscape:cy="128.91168"
+ inkscape:cx="213.59793"
+ inkscape:zoom="2.4559706"
+ inkscape:window-height="1177"
+ inkscape:window-width="1462"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:window-x="899"
+ inkscape:window-y="94"
+ inkscape:current-layer="svg2"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="20"
+ fit-margin-bottom="20" />
+ <g
+ id="g4439"
+ style="filter:url(#filter4485)">
+ <g
+ style="fill:url(#radialGradient4427);fill-opacity:1;stroke:url(#radialGradient4429);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ id="g3"
+ transform="matrix(0.1,0,0,0.1,1.967113,2.4742836)">
+ <g
+ id="g5"
+ style="fill:url(#radialGradient4423);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient4425);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ transform="translate(20.61545,-27.69425)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient4415);fill-opacity:1;stroke:url(#radialGradient4417);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ id="path7"
+ d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient4419);fill-opacity:1;stroke:url(#radialGradient4421);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ id="path9"
+ d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z" />
+ </g>
+ </g>
+ <g
+ transform="matrix(2.8009121,0,0,2.8009121,97.173402,128.84062)"
+ id="g4373"
+ style="fill-rule:evenodd">
+ <path
+ id="rect3922"
+ d="m 30.19825,5.3569063 c 0.5796,0 1.046698,0.6864133 1.046698,1.5381453 l 0,25.8484734 c 0,0.851692 -0.467114,1.538145 -1.046698,1.538145 l -29.0366268,0 c -0.57960004,0 -1.04669856,-0.686421 -1.04669856,-1.538145 0,0 0.002884,-25.8275138 2.6458e-4,-25.8479191 0,-0.8516925 0.46711441,-1.5381453 1.04669858,-1.5381453 l 29.0366272,0 z"
+ inkscape:connector-curvature="0"
+ style="fill:#333333;stroke:#000000;stroke-width:0.22984983"
+ sodipodi:nodetypes="cssssccscc" />
+ <path
+ style="fill:#999999;stroke:#000000;stroke-width:0.26240885"
+ id="path4952"
+ d="m 4.3596675,0.13120443 0,0.7176181 -1.2452482,3.12200877 0,1.4500325 5.4990161,0 0,-1.4500325 -1.2406962,-3.12200877 0,-0.7176181 -3.0131735,0 z m 6.6261025,0 0,0.7176181 -1.2452487,3.12200877 0,1.4500325 5.4990167,0 0,-1.4500325 -1.240696,-3.12200877 0,-0.7176181 -3.013174,0 z m 6.621594,0 0,0.7176181 -1.240696,3.12200877 0,1.4500325 5.499015,0 0,-1.4500325 -1.240696,-3.12200877 0,-0.7176181 -3.017682,0 z m 6.626102,0 0,0.7176181 -1.240696,3.12200877 0,1.4500325 5.499015,0 0,-1.4500325 -1.240696,-3.12200877 0,-0.7176181 -3.017682,0 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc" />
+ <path
+ style="fill:#999999;stroke:#000000;stroke-width:0.26240885"
+ id="path4974"
+ d="m 3.1147829,34.371248 0,1.450032 1.2452481,3.122009 0,0.717618 3.0131736,0 0,-0.717618 1.2406961,-3.122009 0,-1.450032 -5.499016,0 z m 6.626102,0 0,1.450032 1.2452481,3.122009 0,0.717618 3.013173,0 0,-0.717618 1.240697,-3.122009 0,-1.450032 -5.4990163,0 z m 6.6261021,0 0,1.450032 1.240696,3.122009 0,0.717618 3.017683,0 0,-0.717618 1.240696,-3.122009 0,-1.450032 -5.499017,0 z m 6.626102,0 0,1.450032 1.240696,3.122009 0,0.717618 3.017683,0 0,-0.717618 1.240696,-3.122009 0,-1.450032 -5.499017,0 z"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc" />
+ </g>
+ </g>
+</svg>
--- /dev/null
+altusmetrum-micropeak.svg
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ width="214.27165"
+ height="266.00192"
+ version="1.0"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="application-vnd.altusmetrum.telemetry.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/keithp/src/cc1111/altus-logo/bottom.png"
+ inkscape:export-xdpi="119.89881"
+ inkscape:export-ydpi="119.89881">
+ <metadata
+ id="metadata14">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs12">
+ <linearGradient
+ id="linearGradient3165">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3167" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3169" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3177">
+ <stop
+ style="stop-color:#da7000;stop-opacity:1;"
+ offset="0"
+ id="stop3179" />
+ <stop
+ id="stop3447"
+ offset="0.24528302"
+ style="stop-color:#a63852;stop-opacity:1;" />
+ <stop
+ style="stop-color:#7200a4;stop-opacity:1;"
+ offset="1"
+ id="stop3181" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3169">
+ <stop
+ style="stop-color:#ff8a00;stop-opacity:1;"
+ offset="0"
+ id="stop3171" />
+ <stop
+ id="stop3445"
+ offset="0.71698111"
+ style="stop-color:#c24573;stop-opacity:0.98039216;" />
+ <stop
+ style="stop-color:#8500e7;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3173" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 121 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="191 : 121 : 1"
+ inkscape:persp3d-origin="95.5 : 80.666667 : 1"
+ id="perspective16" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3175"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3171"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3020"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3022"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3024"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3026"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3169"
+ id="radialGradient3028"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="2305.2668"
+ fx="951.68713"
+ fy="2305.2668"
+ r="951.68701" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3165"
+ id="radialGradient3030"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
+ cx="951.68713"
+ cy="1205.2668"
+ fx="951.68713"
+ fy="1205.2668"
+ r="951.68701" />
+ <filter
+ id="filter3005"
+ inkscape:label="Drop Shadow"
+ color-interpolation-filters="sRGB">
+ <feFlood
+ id="feFlood3007"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite3009"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur3011"
+ stdDeviation="80"
+ result="blur" />
+ <feOffset
+ id="feOffset3013"
+ dx="100"
+ dy="100"
+ result="offset" />
+ <feComposite
+ id="feComposite3015"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ <filter
+ id="filter4113"
+ style="color-interpolation-filters:sRGB;"
+ inkscape:label="Drop Shadow">
+ <feFlood
+ id="feFlood4115"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite4117"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur4119"
+ in="composite"
+ stdDeviation="6"
+ result="blur" />
+ <feOffset
+ id="feOffset4121"
+ dx="7.5"
+ dy="7.5"
+ result="offset" />
+ <feComposite
+ id="feComposite4123"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ <filter
+ id="filter4125"
+ style="color-interpolation-filters:sRGB;"
+ inkscape:label="Drop Shadow">
+ <feFlood
+ id="feFlood4127"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite4129"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur4131"
+ in="composite"
+ stdDeviation="6"
+ result="blur" />
+ <feOffset
+ id="feOffset4133"
+ dx="7.5"
+ dy="7.5"
+ result="offset" />
+ <feComposite
+ id="feComposite4135"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ <filter
+ id="filter3082"
+ style="color-interpolation-filters:sRGB;"
+ inkscape:label="Drop Shadow">
+ <feFlood
+ id="feFlood3084"
+ flood-opacity="0.604"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite3086"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur3088"
+ in="composite"
+ stdDeviation="6"
+ result="blur" />
+ <feOffset
+ id="feOffset3090"
+ dx="7.5"
+ dy="7.5"
+ result="offset" />
+ <feComposite
+ id="feComposite3092"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ inkscape:cy="184.51843"
+ inkscape:cx="98.017058"
+ inkscape:zoom="1.7366335"
+ inkscape:window-height="1177"
+ inkscape:window-width="1462"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:window-x="225"
+ inkscape:window-y="54"
+ inkscape:current-layer="svg2"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="20"
+ fit-margin-bottom="20" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.98999999000000005;fill:none;fill-opacity:1;stroke:#8a08e8;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path3011"
+ sodipodi:cx="328.79059"
+ sodipodi:cy="127.97095"
+ sodipodi:rx="40.106342"
+ sodipodi:ry="37.459732"
+ d="m 368.89693,127.97095 a 40.106342,37.459732 0 1 1 -80.21268,0 40.106342,37.459732 0 1 1 80.21268,0 z" />
+ <g
+ id="g3032"
+ style="filter:url(#filter3082)">
+ <g
+ style="fill:url(#radialGradient3175);fill-opacity:1;stroke:url(#radialGradient3171);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ id="g3"
+ transform="matrix(0.1,0,0,0.1,1.967113,2.4742836)">
+ <g
+ id="g5"
+ style="fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3030);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ transform="translate(20.61545,-27.69425)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient3020);fill-opacity:1;stroke:url(#radialGradient3022);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ id="path7"
+ d="m 931.07168,1164.597 248.86992,-331.80265 416.1687,1338.32935 286.6484,267.1042 -520.4224,0 -270.2797,-262.2181 0,-1033.0627 -160.98492,106.6818 -160.98492,-106.6818 0,1033.0627 -270.2797,262.2181 -520.4224,0 286.6484,-267.1042 416.1687,-1338.32935 248.86992,331.80265 z" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient3024);fill-opacity:1;stroke:url(#radialGradient3026);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ id="path9"
+ d="m 931.07168,27.69425 224.03682,720.46517 -63.341,76.00913 L 931.07168,486.3269 770.37586,824.16855 707.03486,748.15942 931.07168,27.69425 z" />
+ </g>
+ </g>
+ <g
+ transform="translate(16.698976,134.16763)"
+ id="g3916">
+ <path
+ style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+ inkscape:connector-curvature="0"
+ d="m 117.80725,-96.247891 c 0,0 5.41921,5.552354 5.41921,16.111148 m -5.41921,16.044574 c 0,0 5.41921,-5.552354 5.41921,-16.111149"
+ id="path14345" />
+ <path
+ style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+ inkscape:connector-curvature="0"
+ d="m 136.30179,-112.33241 c 0,0 10.83841,11.11802 10.83841,32.235612 m -10.83841,32.089148 c 0,0 10.83841,-11.104709 10.83841,-32.222298"
+ id="path14347" />
+ <path
+ style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+ inkscape:connector-curvature="0"
+ d="m 156.46069,-128.40361 c 0,0 16.27093,16.65706 16.27093,48.333442 m -16.27093,48.147037 c 0,0 16.27093,-16.670379 16.27093,-48.346762"
+ id="path14349" />
+ </g>
+ <g
+ transform="translate(-17.850629,134.16763)"
+ id="g3911">
+ <path
+ style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+ inkscape:connector-curvature="0"
+ d="m 77.476121,-96.247891 c 0,0 -5.419205,5.552354 -5.419205,16.111148 m 5.419205,16.044574 c 0,0 -5.419205,-5.552354 -5.419205,-16.111149"
+ id="path14351" />
+ <path
+ style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+ inkscape:connector-curvature="0"
+ d="m 59.554132,-112.33241 c 0,0 -10.851724,11.11802 -10.851724,32.235612 m 10.851724,32.089148 c 0,0 -10.851724,-11.104709 -10.851724,-32.222298"
+ id="path14353" />
+ <path
+ style="fill:#8a0ae8;fill-opacity:1;fill-rule:evenodd;stroke:#8a0ae8;stroke-width:8.48192120000000038;stroke-linecap:round;stroke-opacity:1;"
+ inkscape:connector-curvature="0"
+ d="m 39.381908,-128.40361 c 0,0 -16.257613,16.65706 -16.257613,48.333442 m 16.257613,48.147037 c 0,0 -16.257613,-16.670379 -16.257613,-48.346762"
+ id="path14355" />
+ </g>
+ </g>
+</svg>
--- /dev/null
+# To create linux icons and file associations
+
+1) Create mime type and install
+
+ http://www.freedesktop.org/wiki/Specifications/AddingMIMETutor/
+
+ # xdg-mime install --mode system org-altusmetrum-mimetypes.xml
+ # update-mime-database /usr/local/share/mime
+
+ On debian,
+
+2) Create icons and install
+
+ For mime type application/vnd.altusmetrum.telemetry
+ icon name application-vnd.altusmetrum.telemetry.svg
+
+ All mime icons go in
+
+ /usr/share/icons/hicolor/scalable/mimetypes
+
+ Update the icon database
+
+ # update-icon-caches /usr/share/icons/hicolor
+
+3) Create .desktop file and install
+
+ # xdg-desktop-menu install --mode system altusmetrum-altosui.desktop
+
+ # update-desktop-database
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="49.03825"
- height="43.606411"
- id="svg2"
- version="1.1"
- inkscape:version="0.48.4 r9939"
- sodipodi:docname="micropeak.svg">
- <defs
- id="defs4">
- <linearGradient
- id="linearGradient5343">
- <stop
- style="stop-color:#7200a4;stop-opacity:1;"
- offset="0"
- id="stop5345" />
- <stop
- style="stop-color:#da7000;stop-opacity:1;"
- offset="1"
- id="stop5347" />
- </linearGradient>
- <marker
- inkscape:stockid="Arrow2Send"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow2Send"
- style="overflow:visible">
- <path
- id="path3798"
- style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
- d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
- transform="matrix(-0.3,0,0,-0.3,0.69,0)"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:stockid="Arrow1Send"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow1Send"
- style="overflow:visible">
- <path
- id="path3780"
- d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
- transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:stockid="Arrow2Mend"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow2Mend"
- style="overflow:visible">
- <path
- id="path3792"
- style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
- d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
- transform="scale(-0.6,-0.6)"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:stockid="Arrow1Lend"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow1Lend"
- style="overflow:visible">
- <path
- id="path3768"
- d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- inkscape:connector-curvature="0" />
- </marker>
- <marker
- inkscape:stockid="Arrow2Lend"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow2Lend"
- style="overflow:visible">
- <path
- id="path3786"
- style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
- d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
- transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
- inkscape:connector-curvature="0" />
- </marker>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient5343"
- id="linearGradient5349"
- x1="255.48561"
- y1="275.90405"
- x2="280.61411"
- y2="275.90405"
- gradientUnits="userSpaceOnUse" />
- <filter
- id="filter3027"
- inkscape:label="Drop Shadow"
- color-interpolation-filters="sRGB">
- <feFlood
- id="feFlood3029"
- flood-opacity="0.604"
- flood-color="rgb(0,0,0)"
- result="flood" />
- <feComposite
- id="feComposite3031"
- in2="SourceGraphic"
- in="flood"
- operator="in"
- result="composite1" />
- <feGaussianBlur
- id="feGaussianBlur3033"
- stdDeviation="1.6"
- result="blur" />
- <feOffset
- id="feOffset3035"
- dx="2"
- dy="2"
- result="offset" />
- <feComposite
- id="feComposite3037"
- in2="offset"
- in="SourceGraphic"
- operator="over"
- result="composite2" />
- </filter>
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="8.160856"
- inkscape:cx="33.152671"
- inkscape:cy="27.859227"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:window-width="1277"
- inkscape:window-height="894"
- inkscape:window-x="543"
- inkscape:window-y="242"
- inkscape:window-maximized="0"
- fit-margin-top="-3"
- fit-margin-left="-4"
- fit-margin-right="-1"
- fit-margin-bottom="0" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-241.43522,-252.43073)">
- <g
- id="g3000"
- style="filter:url(#filter3027)">
- <g
- id="text2985"
- style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#7200a4;fill-opacity:1;stroke:none;font-family:Minion Pro;-inkscape-font-specification:Minion Pro">
- <path
- inkscape:connector-curvature="0"
- id="path3003"
- style="font-size:36px;font-weight:500;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#7200a4;font-family:ITC Benguiat Gothic Std;-inkscape-font-specification:ITC Benguiat Gothic Std Medium"
- d="m 257.20241,268.30647 c 0,-1.07999 -0.396,-1.872 -1.584,-1.872 -1.188,0 -1.584,0.79201 -1.584,1.872 l 0,8.676 c 0,2.88 -2.052,5.112 -4.824,5.112 -3.06,0 -4.104,-1.872 -4.104,-5.076 l 0,-8.712 c 0,-1.07999 -0.396,-1.872 -1.584,-1.872 -1.188,0 -1.584,0.79201 -1.584,1.872 l 0,21.924 c 0,1.08 0.396,1.872 1.584,1.872 1.188,0 1.584,-0.792 1.584,-1.872 l 0,-6.156 c 0.792,0.612 2.088,0.972 3.564,0.972 2.304,0 4.428,-0.792 5.652,-2.988 l 0.072,0.072 0,1.26 c 0,0.864 0.54,1.44 1.404,1.44 0.864,0 1.404,-0.576 1.404,-1.44 l 0,-15.084" />
- </g>
- <path
- sodipodi:nodetypes="cssc"
- inkscape:connector-curvature="0"
- id="path2991"
- d="m 256.93561,290.70327 c 3.04022,-0.24413 4.30317,-2.66932 5.38268,-5.56604 1.68059,-4.50963 3.67214,-15.86904 8.62227,-20.55527 4.0668,-3.85 8.22354,-3.46656 8.22354,-3.46656"
- style="fill:none;stroke:url(#linearGradient5349);stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:none" />
- <path
- inkscape:transform-center-y="-0.40889198"
- inkscape:transform-center-x="-0.29194889"
- d="m 282.7522,267.42614 -3.93403,-2.77705 -4.51792,1.66641 1.42544,-4.59964 -2.98096,-3.78185 4.815,-0.0657 2.67559,-4.00372 1.55039,4.55904 4.63457,1.30742 -3.85681,2.88333 z"
- inkscape:randomized="0"
- inkscape:rounded="0"
- inkscape:flatsided="false"
- sodipodi:arg2="1.7014539"
- sodipodi:arg1="1.0731354"
- sodipodi:r2="3.6257365"
- sodipodi:r1="7.2514729"
- sodipodi:cy="261.05426"
- sodipodi:cx="279.29056"
- sodipodi:sides="5"
- id="path5341"
- style="fill:none;stroke:#da7000;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- sodipodi:type="star" />
- </g>
- </g>
-</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info
+ xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+ <mime-type type="application/vnd.altusmetrum.telemetry">
+ <comment>Altus Metrum Telemetry File</comment>
+ <glob pattern="*.telem"/>
+ </mime-type>
+ <mime-type type="application/vnd.altusmetrum.eeprom">
+ <comment>Altus Metrum Eeprom Log File</comment>
+ <glob pattern="*.eeprom"/>
+ </mime-type>
+ <mime-type type="application/vnd.altusmetrum.micropeak">
+ <comment>Altus Metrum MicroPeak Log File</comment>
+ <glob pattern="*.mpd"/>
+ </mime-type>
+</mime-info>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="151.43401"
- height="144.50209"
- id="svg2"
- version="1.1"
- inkscape:version="0.48.4 r9939"
- sodipodi:docname="telegps.svg">
- <defs
- id="defs4">
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient3175"
- cx="951.68713"
- cy="2305.2668"
- fx="951.68713"
- fy="2305.2668"
- r="951.68701"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- id="linearGradient3169">
- <stop
- style="stop-color:#ff8a00;stop-opacity:1;"
- offset="0"
- id="stop3171" />
- <stop
- id="stop3445"
- offset="0.71698111"
- style="stop-color:#c24573;stop-opacity:0.98039216;" />
- <stop
- style="stop-color:#8500e7;stop-opacity:0.96078432;"
- offset="1"
- id="stop3173" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient3171"
- cx="951.68713"
- cy="1205.2668"
- fx="951.68713"
- fy="1205.2668"
- r="951.68701"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- id="linearGradient3165">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop3167" />
- <stop
- style="stop-color:#000000;stop-opacity:0;"
- offset="1"
- id="stop3169" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient2838"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="2305.2668"
- fx="951.68713"
- fy="2305.2668"
- r="951.68701" />
- <linearGradient
- id="linearGradient3181">
- <stop
- style="stop-color:#ff8a00;stop-opacity:1;"
- offset="0"
- id="stop3183" />
- <stop
- id="stop3185"
- offset="0.71698111"
- style="stop-color:#c24573;stop-opacity:0.98039216;" />
- <stop
- style="stop-color:#8500e7;stop-opacity:0.96078432;"
- offset="1"
- id="stop3187" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient2840"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="1205.2668"
- fx="951.68713"
- fy="1205.2668"
- r="951.68701" />
- <linearGradient
- id="linearGradient3190">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop3192" />
- <stop
- style="stop-color:#000000;stop-opacity:0;"
- offset="1"
- id="stop3194" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient2830"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="2305.2668"
- fx="951.68713"
- fy="2305.2668"
- r="951.68701" />
- <linearGradient
- id="linearGradient3197">
- <stop
- style="stop-color:#ff8a00;stop-opacity:1;"
- offset="0"
- id="stop3199" />
- <stop
- id="stop3201"
- offset="0.71698111"
- style="stop-color:#c24573;stop-opacity:0.98039216;" />
- <stop
- style="stop-color:#8500e7;stop-opacity:0.96078432;"
- offset="1"
- id="stop3203" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient2832"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="1205.2668"
- fx="951.68713"
- fy="1205.2668"
- r="951.68701" />
- <linearGradient
- id="linearGradient3206">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop3208" />
- <stop
- style="stop-color:#000000;stop-opacity:0;"
- offset="1"
- id="stop3210" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient2834"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="2305.2668"
- fx="951.68713"
- fy="2305.2668"
- r="951.68701" />
- <linearGradient
- id="linearGradient3213">
- <stop
- style="stop-color:#ff8a00;stop-opacity:1;"
- offset="0"
- id="stop3215" />
- <stop
- id="stop3217"
- offset="0.71698111"
- style="stop-color:#c24573;stop-opacity:0.98039216;" />
- <stop
- style="stop-color:#8500e7;stop-opacity:0.96078432;"
- offset="1"
- id="stop3219" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient2836"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- cx="951.68713"
- cy="1205.2668"
- fx="951.68713"
- fy="1205.2668"
- r="951.68701" />
- <linearGradient
- id="linearGradient3222">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop3224" />
- <stop
- style="stop-color:#000000;stop-opacity:0;"
- offset="1"
- id="stop3226" />
- </linearGradient>
- <radialGradient
- r="951.68701"
- fy="2305.2668"
- fx="951.68713"
- cy="2305.2668"
- cx="951.68713"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- gradientUnits="userSpaceOnUse"
- id="radialGradient3232"
- xlink:href="#linearGradient3169"
- inkscape:collect="always" />
- <radialGradient
- r="951.68701"
- fy="1205.2668"
- fx="951.68713"
- cy="1205.2668"
- cx="951.68713"
- gradientTransform="matrix(1,0,0,1.2664529,0,-321.14689)"
- gradientUnits="userSpaceOnUse"
- id="radialGradient3234"
- xlink:href="#linearGradient3165"
- inkscape:collect="always" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3169"
- id="radialGradient4101"
- cx="194.54575"
- cy="361.16367"
- fx="194.54575"
- fy="361.16367"
- r="70.597672"
- gradientTransform="matrix(1,0,0,0.95908583,137.14286,74.776711)"
- gradientUnits="userSpaceOnUse" />
- <filter
- id="filter3238"
- inkscape:label="Drop Shadow"
- color-interpolation-filters="sRGB">
- <feFlood
- id="feFlood3240"
- flood-opacity="0.604"
- flood-color="rgb(0,0,0)"
- result="flood" />
- <feComposite
- id="feComposite3242"
- in2="SourceGraphic"
- in="flood"
- operator="in"
- result="composite1" />
- <feGaussianBlur
- id="feGaussianBlur3244"
- stdDeviation="4"
- result="blur" />
- <feOffset
- id="feOffset3246"
- dx="5"
- dy="5"
- result="offset" />
- <feComposite
- id="feComposite3248"
- in2="offset"
- in="SourceGraphic"
- operator="over"
- result="composite2" />
- </filter>
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="3.959798"
- inkscape:cx="91.754359"
- inkscape:cy="68.172898"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- fit-margin-top="-12"
- fit-margin-left="-12"
- fit-margin-right="-6"
- fit-margin-bottom="-6"
- inkscape:window-width="996"
- inkscape:window-height="970"
- inkscape:window-x="930"
- inkscape:window-y="553"
- inkscape:window-maximized="0" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-258.97144,-351.91262)">
- <path
- style="fill:url(#radialGradient4101);fill-opacity:1;filter:url(#filter3238)"
- d="m 261.09094,466.61035 1.9122,-1.69399 39.0721,-36.4688 20.74158,22.05252 -40.71991,38.37279 z m 36.24983,1.34654 -14.08636,-15.38433 -15.33887,14.40857 14.50759,15.23741 z m 18.98704,-17.58715 -14.47613,-15.53942 -14.95191,14.42099 14.19976,15.37575 z m 43.2565,3.24033 -5.69326,-6.00917 -2.76929,1.85727 c -5.01515,3.36349 -10.61773,4.75193 -13.55344,3.35884 -0.90785,-0.4308 -11.20677,-10.85557 -16.46128,-16.61505 -6.3177,-6.92484 -17.77225,-18.68338 -18.08204,-21.53696 l -0.25491,-2.34789 -6.68224,-3.00173 -6.68224,-3.00173 -0.12416,-2.54849 c -0.24316,-4.99109 2.61694,-11.66135 7.10652,-16.57368 6.51922,-7.13306 14.23173,-10.81215 21.4071,-10.21178 l 2.49577,0.20881 2.34108,7.3087 2.34109,7.3087 2.0542,0.21626 c 1.12981,0.11895 2.29245,0.36702 2.58364,0.55127 0.29119,0.18424 11.17756,11.55849 16.63562,17.46044 5.67391,6.13537 16.35301,17.71615 16.74619,18.65715 1.36492,3.26672 -0.56522,9.34479 -4.44838,14.00803 -0.92939,1.1161 -1.6875,2.14976 -1.6847,2.29703 0.003,0.14726 2.44601,2.88431 5.42933,6.08233 2.98332,3.19801 5.42421,6.02814 5.42421,6.28919 0,0.66794 -0.91528,1.72591 -1.73982,2.01104 -0.50334,0.17406 -2.27007,-1.42112 -6.38899,-5.76858 z m -13.8944,-6.52384 c 0.96195,-0.49074 2.46683,-1.3673 3.34417,-1.94791 l 1.59519,-1.05564 -1.69025,-1.72225 c -1.71532,-1.74777 -2.09589,-2.99732 -1.1891,-3.90412 0.98407,-0.98406 2.33559,-0.53387 3.9423,1.31314 l 1.57825,1.81431 1.43638,-1.7099 c 1.7115,-2.03742 3.3933,-5.47555 3.39008,-6.9304 -0.0104,-4.68327 -7.01613,-2.68794 -13.36898,3.80766 -4.26282,4.35861 -6.32786,9.57528 -4.26584,10.77629 1.19252,0.69458 3.36009,0.51166 5.2278,-0.44118 z m -37.53066,-44.39022 c 2.23934,-2.70633 7.29399,-6.99375 10.13666,-8.59806 1.69887,-0.95877 2.21231,-1.46174 2.04152,-1.99985 -0.1255,-0.3954 -1.05734,-3.0661 -2.07077,-5.93487 l -1.84259,-5.21596 -1.60649,0.12825 c -4.1301,0.32972 -9.06228,2.86043 -13.29918,6.82384 -4.03277,3.77245 -7.7843,10.20829 -7.89014,13.53572 l -0.0463,1.4539 5.4085,2.47197 5.4085,2.47197 1.02919,-1.54008 c 0.56606,-0.84704 1.79503,-2.46562 2.73105,-3.59683 z m 32.91039,-10.47213 40.55794,-38.76942 c 7.09795,7.71166 14.5366,15.63755 20.65837,22.2503 l -40.53088,38.2414 z m 35.73645,1.02093 -14.2595,-15.3791 -15.29495,14.35785 14.65467,15.14661 z m 18.6801,-17.55816 -14.10162,-15.40128 -15.32812,14.3973 14.52992,15.24342 z"
- id="path3063"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccccccccccccccscssascccssscccscasscsssssccssscssssscssscssccccsccccccccccccccccc" />
- </g>
-</svg>
--- /dev/null
+__stdcall
+WinMain(int a, int b, int c, int d) { return 0; }
endif
-
-LIBS=-lbluetooth
+LIBS=-ldl
HFILES=libaltos.h
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;
return 0;
ii = &bt_list->ii[bt_list->rsp];
- ba2str(&ii->bdaddr, device->addr);
+ 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),
struct altos_file *file;
file = calloc(1, sizeof (struct altos_file));
- if (!file)
+ if (!file) {
+ errno = ENOMEM;
+ altos_set_last_posix_error();
goto no_file;
+ }
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = 1;
- str2ba(device->addr, &addr.rc_bdaddr);
+ 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);
MicroPeak-Linux-*
MicroPeak-Mac-*
MicroPeak-Windows-*
-micropeak.desktop
+*.desktop
*.dll
*.dylib
*.so
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
- <string>MicroPeak.icns</string>
+ <string>altusmetrum-micropeak.icns</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>MicroPeak data file</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>application-vnd.altusmetrum.micropeak.icns</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>mpd</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ </array>
<key>Java</key>
<dict>
<key>MainClass</key>
ICONDIR=$(top_srcdir)/icon
JAVA_ICONS=\
- $(ICONDIR)/micropeak-16.png \
- $(ICONDIR)/micropeak-32.png \
- $(ICONDIR)/micropeak-48.png \
- $(ICONDIR)/micropeak-64.png \
- $(ICONDIR)/micropeak-128.png \
- $(ICONDIR)/micropeak-256.png
+ $(ICONDIR)/altusmetrum-micropeak-16.png \
+ $(ICONDIR)/altusmetrum-micropeak-32.png \
+ $(ICONDIR)/altusmetrum-micropeak-48.png \
+ $(ICONDIR)/altusmetrum-micropeak-64.png \
+ $(ICONDIR)/altusmetrum-micropeak-128.png\
+ $(ICONDIR)/altusmetrum-micropeak-256.png
# icon base names for jar
-ICONJAR= -C $(ICONDIR) micropeak-16.png \
- -C $(ICONDIR) micropeak-32.png \
- -C $(ICONDIR) micropeak-48.png \
- -C $(ICONDIR) micropeak-64.png \
- -C $(ICONDIR) micropeak-128.png \
- -C $(ICONDIR) micropeak-256.png
-
-WINDOWS_ICON=$(ICONDIR)/micro-peak.ico
-MACOSX_ICON=$(ICONDIR)/MicroPeak.icns
+ICONJAR= \
+ -C $(ICONDIR) altusmetrum-micropeak-16.png \
+ -C $(ICONDIR) altusmetrum-micropeak-32.png \
+ -C $(ICONDIR) altusmetrum-micropeak-48.png \
+ -C $(ICONDIR) altusmetrum-micropeak-64.png \
+ -C $(ICONDIR) altusmetrum-micropeak-128.png\
+ -C $(ICONDIR) altusmetrum-micropeak-256.png
+
+WINDOWS_ICONS =\
+ ../icon/altusmetrum-micropeak.ico \
+ ../icon/altusmetrum-micropeak.exe
+ ../icon/application-vnd.altusmetrum.micropeak.ico \
+ ../icon/application-vnd.altusmetrum.micropeak.ico
+
+MACOSX_ICONS =\
+ ../icon/altusmetrum-micropeak.icns \
+ ../icon/application-vnd.altusmetrum.micropeak.icns
+
+LINUX_ICONS =\
+ $(ICONDIR)/altusmetrum-micropeak.svg \
+ $(ICONDIR)/application-vnd.altusmetrum.micropeak.svg
+
+LINUX_MIMETYPE =\
+ $(ICONDIR)/org-altusmetrum-mimetypes.xml
desktopdir = $(datadir)/applications
-desktop_file = micropeak.desktop
+desktop_file = altusmetrum-micropeak.desktop
desktop_SCRIPTS = $(desktop_file)
all-local: micropeak-test micropeak-jdb $(JAR)
$(ALTOSUILIB_CLASS) \
$(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt \
micropeak micropeak-test micropeak-jdb macosx linux windows micropeak-windows.log \
- micropeak-windows.nsi
+ micropeak-windows.nsi *.desktop
EXTRA_DIST = $(desktop_file).in
$(desktop_file): $(desktop_file).in
- sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/micropeak.desktop.in > $@
+ sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/$(desktop_file).in > $@
chmod +x $@
LINUX_DIST=MicroPeak-Linux-$(VERSION).tar.bz2
FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS)
-LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) micropeak.desktop.in ../icon/micropeak.svg
-LINUX_EXTRA=micropeak-fat micropeak.desktop.in
+LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) $(desktop_file).in $(LINUX_ICONS) $(LINUX_MIMETYPE)
+LINUX_EXTRA=micropeak-fat $(desktop_file).in
MACOSX_DRIVER_URL=http://www.ftdichip.com/Drivers/VCP/MacOSX/FTDIUSBSerialDriver_v2_2_18.dmg
MACOSX_DRIVER=FTDIUSBSerialDriver_v2_2_18.dmg
MACOSX_INFO_PLIST=Info.plist
MACOSX_README=ReadMe-Mac.rtf
-MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVER) $(MACOSX_README) $(DOC) $(MACOSX_ICON)
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVER) $(MACOSX_README) $(DOC) $(MACOSX_ICONS)
$(MACOSX_DRIVER):
wget $(MACOSX_DRIVER_URL)
$(WINDOWS_DRIVER):
wget $(WINDOWS_DRIVER_URL)
-WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(DOC) $(WINDOWS_ICON) $(WINDOWS_DRIVER)
+WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(DOC) $(WINDOWS_ICONS) $(WINDOWS_DRIVER)
if FATINSTALL
cp -p Info.plist macosx/MicroPeak.app/Contents
cp -p $(MACOSX_DRIVER) macosx
mkdir -p macosx/MicroPeak.app/Contents/Resources/Java
- cp -p $(MACOSX_ICON) macosx/MicroPeak.app/Contents/Resources
+ cp -p $(MACOSX_ICONS) macosx/MicroPeak.app/Contents/Resources
cp -p $(FATJAR) macosx/MicroPeak.app/Contents/Resources/Java/micropeak.jar
cp -p libaltos.dylib macosx/MicroPeak.app/Contents/Resources/Java
cp -p $(ALTOSLIB_CLASS) macosx/MicroPeak.app/Contents/Resources/Java
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
class MicroIterator implements Iterator<MicroDataPoint> {
int i;
private double time_step;
private double ground_altitude;
private ArrayList<Integer> bytes;
+ public int log_id;
String name;
MicroStats stats;
-
+
+ public static final int LOG_ID_MICROPEAK = 0;
+ public static final int LOG_ID_MICROKITE = 1;
+
+ public static final double CLOCK = 0.096;
+
public class FileEndedException extends Exception {
}
if (get_nonwhite(f) == 'M' && get_nonwhite(f) == 'P')
return true;
}
- }
+ }
private int get_32(InputStream f) throws IOException, FileEndedException, NonHexcharException {
int v = 0;
ground_pressure = get_32(f);
min_pressure = get_32(f);
int nsamples = get_16(f);
+
+ log_id = nsamples >> 12;
+ nsamples &= 0xfff;
pressures = new int[nsamples + 1];
ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure);
else
cur = down;
}
-
+
pressures[i+1] = cur;
}
crc_valid = crc == current_crc;
- time_step = 0.192;
+ switch (log_id) {
+ case LOG_ID_MICROPEAK:
+ time_step = 2 * CLOCK;
+ break;
+ case LOG_ID_MICROKITE:
+ time_step = 200 * CLOCK;
+ break;
+ }
stats = new MicroStats(this);
} catch (FileEndedException fe) {
throw new IOException("File Ended Unexpectedly");
pressures = new int[1];
pressures[0] = 101000;
}
-
+
}
package org.altusmetrum.micropeak;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroDataPoint implements AltosUIDataPoint {
public double time;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroDeviceDialog extends AltosDeviceDialog {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
MicroPeak owner;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroExport extends JFileChooser {
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroFile {
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroFileChooser extends JFileChooser {
JFrame frame;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroFrame extends AltosUIFrame {
static String[] micro_icon_names = {
- "/micropeak-16.png",
- "/micropeak-32.png",
- "/micropeak-48.png",
- "/micropeak-64.png",
- "/micropeak-128.png",
- "/micropeak-256.png"
+ "/altusmetrum-micropeak-16.png",
+ "/altusmetrum-micropeak-32.png",
+ "/altusmetrum-micropeak-48.png",
+ "/altusmetrum-micropeak-64.png",
+ "/altusmetrum-micropeak-128.png",
+ "/altusmetrum-micropeak-256.png"
};
static { set_icon_names(micro_icon_names); }
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
private void DownloadData() {
AltosDevice device = MicroDeviceDialog.show(this);
-
+
if (device != null)
new MicroDownload(this, device);
}
if (save.runDialog())
SetName(data.name);
}
-
+
private void Export() {
if (data == null) {
no_data();
public void itemStateChanged(ItemEvent e) {
}
+ /* OSXAdapter interfaces */
+ public void macosx_file_handler(String path) {
+ CommandGraph(new File(path));
+ }
+
+ public void macosx_quit_handler() {
+ System.exit(0);
+ }
+
+ public void macosx_preferences_handler() {
+ Preferences();
+ }
+
public MicroPeak() {
++number_of_windows;
+ register_for_macosx_events();
+
AltosUIPreferences.set_component(this);
container = getContentPane();
import java.awt.*;
import java.io.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroRaw extends JTextArea {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroSave extends JFileChooser {
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroSerial extends InputStream {
SWIGTYPE_p_altos_file file;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public interface MicroSerialLog {
package org.altusmetrum.micropeak;
import java.io.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroStats {
double coast_height;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public class MicroUSB extends altos_device implements AltosDevice {
--- /dev/null
+[Desktop Entry]
+Type=Application
+Name=MicroPeak
+GenericName=MicroPeak Download and Analysis
+Comment=View and log data from MicroPeak altimeters
+Icon=%icondir%/altusmetrum-micropeak.svg
+Exec=%bindir%/micropeak %f
+Terminal=false
+MimeType=application/vnd.altusmetrum.micropeak
+Categories=Education;Electronics;Science;
-!addplugindir Instdrv/NSIS/Plugins
+!addplugindir ../altosui/Instdrv/NSIS/Plugins
!addincludedir ../altosui/Instdrv/NSIS/Includes
!include x64.nsh
!include java.nsh
+!include refresh-sh.nsh
-Name "Altus Metrum MicroPeak Installer"
+!define REG_NAME "MicroPeak"
+!define PROG_ID "org.altusmetrum.micropeak.1"
+!define PROG_ID_MPD "org.altusmetrum.micropeak.mpd.1"
+!define FAT_NAME "micropeak-fat.jar"
+!define WIN_APP_ICON "altusmetrum-micropeak.ico"
+!define WIN_APP_EXE "altusmetrum-micropeak.exe"
+!define WIN_MPD_EXE "application-vnd.altusmetrum.micropeak.exe"
+
+Name "${REG_NAME} Installer"
; Default install directory
InstallDir "$PROGRAMFILES\AltusMetrum"
; Tell the installer where to re-install a new version
-InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+InstallDirRegKey HKLM "Software\${REG_NAME}" "Install_Dir"
LicenseText "GNU General Public License Version 2"
LicenseData "../COPYING"
ShowInstDetails Show
-ComponentText "Altus Metrum MicroPeak Software Installer"
+ComponentText "${REG_NAME} Software and Driver Installer"
Function .onInit
DetailPrint "Checking host operating system"
${EndIf}
FunctionEnd
+Function un.onInit
+ DetailPrint "Checking host operating system"
+ ${If} ${RunningX64}
+ DetailPrint "Installer running on 64-bit host"
+ SetRegView 64
+ StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+ ${DisableX64FSRedirection}
+ ${EndIf}
+FunctionEnd
+
; Pages to present
Page license
; And the stuff to install
-Section "MicroPeak Application"
+Section "FTDI USB Driver"
+ SetOutPath $INSTDIR
+
+ File "CDM20824_Setup.exe"
+
+ StrCpy $2 "$INSTDIR\CDM20824_Setup.exe"
+ ExecWait $2
+SectionEnd
+
+Section "${REG_NAME} Application"
Call DetectJRE
SetOutPath $INSTDIR
- File "micropeak-fat.jar"
+ File "${FAT_NAME}"
File "altoslib_@ALTOSLIB_VERSION@.jar"
File "altosuilib_@ALTOSUILIB_VERSION@.jar"
File "jfreechart.jar"
File "*.dll"
- File "../icon/*.ico"
-
- CreateShortCut "$SMPROGRAMS\MicroPeak.lnk" "$SYSDIR\javaw.exe" "-jar micropeak-fat.jar" "$INSTDIR\micro-peak.ico"
-SectionEnd
-
-Section "FTDI USB Driver"
- SetOutPath $INSTDIR
-
- File "CDM20824_Setup.exe"
+ File "../icon/${WIN_APP_ICON}"
- StrCpy $2 "$INSTDIR\CDM20824_Setup.exe"
- ExecWait $2
+ CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
-Section "MicroPeak Desktop Shortcut"
- CreateShortCut "$DESKTOP\MicroPeak.lnk" "$INSTDIR\micropeak-fat.jar" "" "$INSTDIR\micro-peak.ico"
+Section "${REG_NAME} Desktop Shortcut"
+ CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
Section "Documentation"
File "../doc/micropeak.pdf"
SectionEnd
+Section "File Associations"
+
+ SetOutPath $INSTDIR
+
+ File "../icon/${WIN_APP_EXE}"
+ File "../icon/${WIN_MPD_EXE}"
+
+ ; application elements
+
+ DeleteRegKey HKCR "${PROG_ID}"
+ DeleteRegKey HKCR "${PROG_ID_MPD}"
+
+ WriteRegStr HKCR "${PROG_ID_MPD}" "" "MicroPeak Data File"
+ WriteRegStr HKCR "${PROG_ID_MPD}" "FriendlyTypeName" "MicroPeak Data File"
+ WriteRegStr HKCR "${PROG_ID_MPD}\CurVer" "" "${PROG_ID_MPD}"
+ WriteRegStr HKCR "${PROG_ID_MPD}\DefaultIcon" "" '"$INSTDIR\${WIN_MPD_EXE}",-101'
+ WriteRegExpandStr HKCR "${PROG_ID_MPD}\shell\play\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+ ; .mpd elements
+
+ WriteRegStr HKCR ".mpd" "" "${PROG_ID_MPD}"
+ WriteRegStr HKCR ".mpd" "PerceivedType" "MicroPeak Data File"
+ WriteRegStr HKCR ".mpd" "Content Type" "application/vnd.altusmetrum.micropeak"
+
+ WriteRegStr HKCR ".mpd\OpenWithProgids" "${PROG_ID_MPD}" ""
+ WriteRegStr HKCR ".mpd\${PROG_ID_MPD}" "" "${REG_NAME}"
+
+ Call RefreshShellIcons
+SectionEnd
+
Section "Uninstaller"
; Deal with the uninstaller
+ ${DisableX64FSRedirection}
SetOutPath $INSTDIR
; Write the install path to the registry
- WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR"
+ WriteRegStr HKLM "SOFTWARE\${REG_NAME}" "Install_Dir" "$INSTDIR"
; Write the uninstall keys for windows
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"'
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "DisplayName" "${REG_NAME}"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "UninstallString" '"$INSTDIR\uninstall-${REG_NAME}.exe"'
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoModify" "1"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoRepair" "1"
- WriteUninstaller "uninstall.exe"
+ WriteUninstaller "uninstall-${REG_NAME}.exe"
SectionEnd
Section "Uninstall"
- DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
- DeleteRegKey HKLM "Software\AltusMetrum"
- Delete "$INSTDIR\*.*"
- RMDir "$INSTDIR"
+ ${DisableX64FSRedirection}
+
+ DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}"
+ DeleteRegKey HKLM "SOFTWARE\${REG_NAME}"
+
+ DetailPrint "Delete uninstall reg entries"
+
+ DeleteRegKey HKCR "${PROG_ID}"
+ DeleteRegKey HKCR "${PROG_ID_MPD}"
+
+ DeleteRegKey HKCR ".mpd\${PROG_ID_MPD}"
+ DeleteRegValue HKCR ".mpd\OpenWithProgids" "${PROG_ID_MPD}"
+
+ Delete "$INSTDIR\${FAT_NAME}"
+ Delete "$INSTDIR\uninstall-${REG_NAME}.exe"
+
+ Delete "$INSTDIR\${WIN_APP_ICON}"
+ Delete "$INSTDIR\${WIN_APP_EXE}"
; Remove shortcuts, if any
- Delete "$SMPROGRAMS\MicroPeak.lnk"
- Delete "$DESKTOP\MicroPeak.lnk"
+ Delete "$SMPROGRAMS\${REG_NAME}.lnk"
+ Delete "$DESKTOP\${REG_NAME}.lnk"
+ Call un.RefreshShellIcons
SectionEnd
+++ /dev/null
-[Desktop Entry]
-Type=Application
-Name=MicroPeak
-GenericName=MicroPeak download and analysis
-Comment=View and log data from MicroPeak altimeters
-Icon=%icondir%/micropeak.svg
-Exec=%bindir%/micropeak %f
-Terminal=false
-MimeType=text/plain;
-Categories=Education;Electronics;Science;
telemini-v1.0 telemini-v2.0 \
telebt-v1.0 \
teleterra-v0.2 teleshield-v0.1 \
- telefire-v0.1 telefire-v0.2
+ telefire-v0.1 telefire-v0.2 \
+ telerepeat-v1.0
ARMM3DIRS=\
+ easymega-v1.0 easymega-v1.0/flash-loader \
telemega-v0.1 telemega-v0.1/flash-loader \
telemega-v1.0 telemega-v1.0/flash-loader \
telemetrum-v2.0 telemetrum-v2.0/flash-loader \
easymini-v1.0 easymini-v1.0/flash-loader
AVRDIRS=\
- telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1
+ telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite
SUBDIRS=
all-recursive: all-local
-all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h $(PDCLIB)
+all-local: altitude.h altitude-pa.h altitude-pa-small.h ao_kalman.h ao_whiten.h $(PDCLIB)
altitude.h: make-altitude
nickle $< > $@
altitude-pa.h: make-altitude-pa
nickle $< > $@
-ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c
+altitude-pa-small.h: make-altitude-pa
+ nickle $< --sample 3 > $@
+
+ao_kalman.h: make-kalman kalman.5c kalman_micro.5c kalman_filter.5c load_csv.5c matrix.5c
bash $< kalman > $@
ao_whiten.h: make-whiten
nop
_endasm;
}
+ __critical while (!ao_intflash_dma_done)
+ ao_sleep(&ao_intflash_dma_done);
}
static void
#define HAS_RADIO 1
#define DISABLE_LOG_SPACE 1
+#define AO_VALUE_32 0
+#define HAS_WIDE_GPS 0
#if defined(TELEMETRUM_V_1_0)
/* Discontinued and was never built with CC1111 chips needing this */
#define HAS_ACCEL 1
#define HAS_IGNITE 1
#define HAS_MONITOR 0
+ #define HAS_TELEMETRY 1
+ #define HAS_RADIO_RATE 0 /* not enough space for this */
+ #define HAS_MUTEX_TRY 0
#endif
#if defined(TELEMETRUM_V_1_1)
#define HAS_ACCEL 1
#define HAS_IGNITE 1
#define HAS_MONITOR 0
+ #define HAS_TELEMETRY 1
+ #define HAS_RADIO_RATE 0 /* not enough space for this */
+ #define HAS_MUTEX_TRY 0
#endif
#if defined(TELEMETRUM_V_1_2)
#define HAS_ACCEL 1
#define HAS_IGNITE 1
#define HAS_MONITOR 0
+ #define HAS_TELEMETRY 1
+ #define HAS_RADIO_RATE 0 /* not enough space for this */
+ #define HAS_MUTEX_TRY 0
#endif
#if defined(TELEDONGLE_V_0_2)
#define LEGACY_MONITOR 1
#define HAS_RSSI 1
#define HAS_AES 0
+ #define HAS_TELEMETRY 0
+ #define AO_RADIO_REG_TEST 1
#endif
#if defined(TELEMINI_V_1_0)
#define HAS_ACCEL 0
#define HAS_IGNITE 1
#define HAS_MONITOR 0
+ #define HAS_TELEMETRY 1
+ #define HAS_RADIO_RATE 0 /* not enough space for this */
#endif
#if defined(TELENANO_V_0_1)
#define HAS_ACCEL 0
#define HAS_IGNITE 0
#define HAS_MONITOR 0
+ #define HAS_TELEMETRY 1
+ #define HAS_RADIO_RATE 0 /* not enough space for this */
#endif
#if defined(TELEMETRUM_V_0_1)
#define HAS_ACCEL 1
#define HAS_IGNITE 1
#define HAS_MONITOR 0
+ #define HAS_TELEMETRY 1
+ #define HAS_RADIO_RATE 0 /* not enough space for this */
#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 127 * (uint32_t) 1024)
#endif
#define LEGACY_MONITOR 1
#define HAS_RSSI 1
#define HAS_AES 0
+ #define HAS_TELEMETRY 0
#endif
#if defined(TIDONGLE)
#define LEGACY_MONITOR 1
#define HAS_RSSI 1
#define HAS_AES 0
+ #define HAS_TELEMETRY 0
#endif
#if defined(TELEBT_V_0_0)
#define LEGACY_MONITOR 1
#define HAS_RSSI 0
#define HAS_AES 0
+ #define HAS_TELEMETRY 0
+ #define AO_RADIO_REG_TEST 1
#endif
#if defined(TELEBT_V_0_1)
#define LEGACY_MONITOR 1
#define HAS_RSSI 0
#define HAS_AES 0
+ #define HAS_TELEMETRY 0
+ #define AO_RADIO_REG_TEST 1
#endif
#if defined(TELELAUNCH_V_0_1)
#define HAS_IGNITE 1
#define HAS_MONITOR 0
#define HAS_AES 1
+ #define HAS_TELEMETRY 0
#endif
#if DBG_ON_P1
#define IF_FREQ_CONTROL 6
/*
+ * http://www.ntia.doc.gov/files/ntia/publications/84-168.pdf
+ *
+ * Necessary bandwidth for a FSK modulated signal:
+ *
+ * bw = 2.6d + 0.55b 1.5 < m < 5.5
+ * bw = 2.1d + 1.9b 5.5 < m < 20
+ *
+ * b is the modulation rate in bps
+ * d is the peak deviation (from the center)
+ *
+ * m = 2d / b
+ *
+ * 20.5 kHz deviation 38.4kbps signal:
+ *
+ * m = 41 / 38.4, which is < 5.5:
+ *
+ * bw = 2.6 * 20.5 + 0.55 * 38.4 = 74.42kHz
+ *
+ * M = 1, E = 3, bw = 75kHz
+ *
+ * 5.125 kHz deviation, 9.6kbps signal
+ *
+ * m = 10.25 / 9.6, which is < 5.5:
+ *
+ * bw = 2.6 * 5.125 + 0.55 * 9.6 = 18.6kHz
+ *
+ * M = 2, E = 3, bw = 53.6kHz
+ *
+ * 1.28125kHz deviation, 2.4kbps signal
+ *
+ * m = 2.565 / 2.4, which is < 5.5:
+ *
+ * bw = 2.6 * 20.5 + 1.9 * 2.4 = 47.61kHz
+ *
+ * M = 3, E = 3, bw = 53.6kHz
+ *
* For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are
*
* BW = 24e6 / (8 * (4 + M) * 2 ** E)
* So, M = 0 and E = 3
*/
-#define CHANBW_M 0
+#define CHANBW_M_384 1
+#define CHANBW_M_96 3
+#define CHANBW_M_24 3
#define CHANBW_E 3
/*
*
* R = (256 + M) * 2** E * 24e6 / 2**28
*
- * So M is 163 and E is 10
+ * So for 38360kBaud, M is 163 and E is 10
*/
-#define DRATE_E 10
#define DRATE_M 163
+#define DRATE_E_384 10
+
+/* For 9600 baud, M is 163 and E is 8
+ */
+
+#define DRATE_E_96 8
+
+/* For 2400 baud, M is 163 and E is 6
+ */
+
+#define DRATE_E_24 6
+
/*
* For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are:
*
* F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E
*
- * So M is 6 and E is 3
+ * For 20.5kHz deviation, M is 6 and E is 3
+ * For 5.125kHz deviation, M is 6 and E is 1
+ * For 1.28125kHz deviation, M is 0 and E is 0
*/
-#define DEVIATION_M 6
-#define DEVIATION_E 3
+#define DEVIATION_M_384 6
+#define DEVIATION_E_384 3
+
+#define DEVIATION_M_96 6
+#define DEVIATION_E_96 1
+
+#define DEVIATION_M_24 0
+#define DEVIATION_E_24 0
/*
* For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone),
RF_FSCTRL1_OFF, (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT),
RF_FSCTRL0_OFF, (0 << RF_FSCTRL0_FREQOFF_SHIFT),
- RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
- (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
- (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
- RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF |
+ RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_ON |
RF_MDMCFG2_MOD_FORMAT_GFSK |
- RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+ RF_MDMCFG2_SYNC_MODE_15_16),
RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN |
RF_MDMCFG1_NUM_PREAMBLE_4 |
(2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
RF_CHANNR_OFF, 0,
- RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
- (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
-
/* SmartRF says set LODIV_BUF_CURRENT_TX to 0
* And, we're not using power ramping, so use PA_POWER 0
*/
RF_FSCAL1_OFF, 0x00,
RF_FSCAL0_OFF, 0x1F,
- RF_TEST2_OFF, 0x88,
- RF_TEST1_OFF, 0x31,
+ RF_TEST2_OFF, RF_TEST2_RX_LOW_DATA_RATE_MAGIC,
+ RF_TEST1_OFF, RF_TEST1_RX_LOW_DATA_RATE_MAGIC,
RF_TEST0_OFF, 0x09,
/* default sync values */
RF_BSCFG_BS_POST_KI_PRE_KI|
RF_BSCFG_BS_POST_KP_PRE_KP|
RF_BSCFG_BS_LIMIT_0),
- RF_AGCCTRL2_OFF, 0x03,
- RF_AGCCTRL1_OFF, 0x40,
- RF_AGCCTRL0_OFF, 0x91,
-
+ RF_AGCCTRL2_OFF, (RF_AGCCTRL2_MAX_DVGA_GAIN_ALL|
+ RF_AGCCTRL2_MAX_LNA_GAIN_0|
+ RF_AGCCTRL2_MAGN_TARGET_33dB),
+ RF_AGCCTRL1_OFF, (RF_AGCCTRL1_AGC_LNA_PRIORITY_0 |
+ RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE |
+ RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB),
+ RF_AGCCTRL0_OFF, (RF_AGCCTRL0_HYST_LEVEL_NONE |
+ RF_AGCCTRL0_WAIT_TIME_8 |
+ RF_AGCCTRL0_AGC_FREEZE_NORMAL |
+ RF_AGCCTRL0_FILTER_LENGTH_8),
RF_IOCFG2_OFF, 0x00,
RF_IOCFG1_OFF, 0x00,
RF_IOCFG0_OFF, 0x00,
static __code uint8_t rdf_setup[] = {
RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
- (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
+ (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) |
(RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
RF_MDMCFG3_OFF, (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF |
(RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
/* packet length is set in-line */
- RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)|
+ RF_PKTCTRL1_OFF, ((0 << PKTCTRL1_PQT_SHIFT)|
PKTCTRL1_ADR_CHK_NONE),
RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL|
RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
};
static __code uint8_t fixed_pkt_setup[] = {
+#if !HAS_RADIO_RATE
RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
- (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
- (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
+ (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) |
+ (DRATE_E_384 << RF_MDMCFG4_DRATE_E_SHIFT)),
+#endif
RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
- RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF |
+ RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_ON |
RF_MDMCFG2_MOD_FORMAT_GFSK |
- RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+ RF_MDMCFG2_SYNC_MODE_15_16),
RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN |
RF_MDMCFG1_NUM_PREAMBLE_4 |
(2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
- RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
- (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
+#if !HAS_RADIO_RATE
+ RF_DEVIATN_OFF, ((DEVIATION_E_384 << RF_DEVIATN_DEVIATION_E_SHIFT) |
+ (DEVIATION_M_384 << RF_DEVIATN_DEVIATION_M_SHIFT)),
+#endif
/* max packet length -- now set inline */
RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)|
RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
};
+#if HAS_RADIO_RATE
+static __code struct {
+ uint8_t mdmcfg4;
+ uint8_t deviatn;
+} packet_rate_setup[] = {
+ /* 38400 */
+ {
+ ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+ (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) |
+ (DRATE_E_384 << RF_MDMCFG4_DRATE_E_SHIFT)),
+ ((DEVIATION_E_384 << RF_DEVIATN_DEVIATION_E_SHIFT) |
+ (DEVIATION_M_384 << RF_DEVIATN_DEVIATION_M_SHIFT)),
+ },
+ /* 9600 */
+ {
+ ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+ (CHANBW_M_96 << RF_MDMCFG4_CHANBW_M_SHIFT) |
+ (DRATE_E_96 << RF_MDMCFG4_DRATE_E_SHIFT)),
+ ((DEVIATION_E_96 << RF_DEVIATN_DEVIATION_E_SHIFT) |
+ (DEVIATION_M_96 << RF_DEVIATN_DEVIATION_M_SHIFT)),
+ },
+ /* 2400 */
+ {
+ ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+ (CHANBW_M_24 << RF_MDMCFG4_CHANBW_M_SHIFT) |
+ (DRATE_E_24 << RF_MDMCFG4_DRATE_E_SHIFT)),
+ ((DEVIATION_E_24 << RF_DEVIATN_DEVIATION_E_SHIFT) |
+ (DEVIATION_M_24 << RF_DEVIATN_DEVIATION_M_SHIFT)),
+ },
+};
+#endif
+
__xdata uint8_t ao_radio_dma;
__xdata uint8_t ao_radio_dma_done;
__xdata uint8_t ao_radio_done;
RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8);
RF_FREQ0 = (uint8_t) (ao_config.radio_setting);
RF_PKTLEN = len;
+#if HAS_RADIO_RATE
+ RF_MDMCFG4 = packet_rate_setup[ao_config.radio_rate].mdmcfg4;
+ RF_DEVIATN = packet_rate_setup[ao_config.radio_rate].deviatn;
+#endif
}
ao_radio_test(0);
}
+#if AO_RADIO_REG_TEST
+static void
+ao_radio_set_reg(void)
+{
+ uint8_t offset;
+ ao_cmd_hex();
+ offset = ao_cmd_lex_i;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ ao_cmd_hex();
+ printf("RF[%x] %x", offset, RF[offset]);
+ if (ao_cmd_status == ao_cmd_success) {
+ RF[offset] = ao_cmd_lex_i;
+ printf (" -> %x", RF[offset]);
+ }
+ ao_cmd_status = ao_cmd_success;
+ printf("\n");
+}
+#endif
+
__code struct ao_cmds ao_radio_cmds[] = {
{ ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
+#if AO_RADIO_REG_TEST
+ { ao_radio_set_reg, "V <offset> <value>\0Set radio register" },
+#endif
{ 0, NULL },
};
__xdata __at (0xdf17) uint8_t RF_AGCCTRL2;
#define RF_AGCCTRL2_OFF 0x17
+#define RF_AGCCTRL2_MAX_DVGA_GAIN_ALL (0 << 6)
+#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_1 (1 << 6)
+#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_2 (2 << 6)
+#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_3 (3 << 6)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_0 (0 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_2_6 (1 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_6_1 (2 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_7_4 (3 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_9_2 (4 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_11_5 (5 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_14_6 (6 << 3)
+#define RF_AGCCTRL2_MAX_LNA_GAIN_17_1 (7 << 3)
+#define RF_AGCCTRL2_MAGN_TARGET_24dB (0 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_27dB (1 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_30dB (2 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_33dB (3 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_36dB (4 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_38dB (5 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_40dB (6 << 0)
+#define RF_AGCCTRL2_MAGN_TARGET_42dB (7 << 0)
+
__xdata __at (0xdf18) uint8_t RF_AGCCTRL1;
#define RF_AGCCTRL1_OFF 0x18
+#define RF_AGCCTRL1_AGC_LNA_PRIORITY_0 (0 << 6)
+#define RF_AGCCTRL1_AGC_LNA_PRIORITY_1 (1 << 6)
+#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE (0 << 4)
+#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_6DB (1 << 4)
+#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_10DB (2 << 4)
+#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_14DB (3 << 4)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_DISABLE (0x8 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_BELOW (0x9 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_BELOW (0xa << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_BELOW (0xb << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_BELOW (0xc << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_BELOW (0xd << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_BELOW (0xe << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_BELOW (0xf << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB (0x0 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_ABOVE (0x1 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_ABOVE (0x2 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_ABOVE (0x3 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_ABOVE (0x4 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_ABOVE (0x5 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_ABOVE (0x6 << 0)
+#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_ABOVE (0x7 << 0)
+
__xdata __at (0xdf19) uint8_t RF_AGCCTRL0;
#define RF_AGCCTRL0_OFF 0x19
+#define RF_AGCCTRL0_HYST_LEVEL_NONE (0 << 6)
+#define RF_AGCCTRL0_HYST_LEVEL_LOW (1 << 6)
+#define RF_AGCCTRL0_HYST_LEVEL_MEDIUM (2 << 6)
+#define RF_AGCCTRL0_HYST_LEVEL_HIGH (3 << 6)
+#define RF_AGCCTRL0_WAIT_TIME_8 (0 << 4)
+#define RF_AGCCTRL0_WAIT_TIME_16 (1 << 4)
+#define RF_AGCCTRL0_WAIT_TIME_24 (2 << 4)
+#define RF_AGCCTRL0_WAIT_TIME_32 (3 << 4)
+#define RF_AGCCTRL0_AGC_FREEZE_NORMAL (0 << 2)
+#define RF_AGCCTRL0_AGC_FREEZE_SYNC (1 << 2)
+#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_ANALOG (2 << 2)
+#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_BOTH (3 << 2)
+#define RF_AGCCTRL0_FILTER_LENGTH_8 (0 << 0)
+#define RF_AGCCTRL0_FILTER_LENGTH_16 (1 << 0)
+#define RF_AGCCTRL0_FILTER_LENGTH_32 (2 << 0)
+#define RF_AGCCTRL0_FILTER_LENGTH_64 (3 << 0)
+
__xdata __at (0xdf1a) uint8_t RF_FREND1;
#define RF_FREND1_OFF 0x1a
-/**
+/**
* http://ad7zj.net/kd7lmo/aprsbeacon_code.html
*
* @mainpage Pico Beacon
*
* @section overview_sec Overview
*
- * The Pico Beacon is an APRS based tracking beacon that operates in the UHF 420-450MHz band. The device utilizes a
+ * The Pico Beacon is an APRS based tracking beacon that operates in the UHF 420-450MHz band. The device utilizes a
* Microchip PIC 18F2525 embedded controller, Motorola M12+ GPS engine, and Analog Devices AD9954 DDS. The device is capable
* of generating a 1200bps A-FSK and 9600 bps FSK AX.25 compliant APRS (Automatic Position Reporting System) message.
* (4) corrected size of LOG_COORD block when searching for end of log.
*
* @subsection v303 V3.03
- * 15 Sep 2005, Change include; (1) removed AD9954 setting SDIO as input pin,
+ * 15 Sep 2005, Change include; (1) removed AD9954 setting SDIO as input pin,
* (2) additional comments and Doxygen tags,
* (3) integration and test code calculates DDS FTW,
* (4) swapped bus and reference analog input ports (hardware change),
* (2) Doxygen documentation clean up and additions, and
* (3) added integration and test code to baseline.
*
- *
+ *
* @subsection v301 V3.01
* 13 Jan 2005, Renamed project and files to Pico Beacon.
*
* (8) added flight data recorder, and
* (9) added diagnostics terminal mode.
*
- *
+ *
* @subsection v201 V2.01
- * 30 Jan 2004, Change include; (1) General clean up of in-line documentation, and
+ * 30 Jan 2004, Change include; (1) General clean up of in-line documentation, and
* (2) changed temperature resolution to 0.1 degrees F.
*
- *
+ *
* @subsection v200 V2.00
* 26 Oct 2002, Change include; (1) Micro Beacon II hardware changes including PIC18F252 processor,
- * (2) serial EEPROM,
- * (3) GPS power control,
- * (4) additional ADC input, and
- * (5) LM60 temperature sensor.
+ * (2) serial EEPROM,
+ * (3) GPS power control,
+ * (4) additional ADC input, and
+ * (5) LM60 temperature sensor.
*
*
* @subsection v101 V1.01
- * 5 Dec 2001, Change include; (1) Changed startup message, and
+ * 5 Dec 2001, Change include; (1) Changed startup message, and
* (2) applied SEPARATE pragma to several methods for memory usage.
*
*
* @subsection v100 V1.00
* 25 Sep 2001, Initial release. Flew ANSR-3 and ANSR-4.
- *
+ *
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ *
- *
- *
+ *
+ *
* @section design Design Details
*
* Provides design details on a variety of the components that make up the Pico Beacon.
* @page power Power Consumption
*
* Measured DC power consumption.
- *
- * 3VDC prime power current
+ *
+ * 3VDC prime power current
*
- * 7mA Held in reset
+ * 7mA Held in reset
- * 18mA Processor running, all I/O off
+ * 18mA Processor running, all I/O off
- * 110mA GPS running
+ * 110mA GPS running
- * 120mA GPS running w/antenna
+ * 120mA GPS running w/antenna
- * 250mA DDS running and GPS w/antenna
+ * 250mA DDS running and GPS w/antenna
- * 420mA DDS running, GPS w/antenna, and PA chain on with no RF
+ * 420mA DDS running, GPS w/antenna, and PA chain on with no RF
- * 900mA Transmit
+ * 900mA Transmit
*
*/
#ifndef AO_APRS_TEST
#include <ao.h>
+
+#if !HAS_APRS
+#error HAS_APRS not set
+#endif
#endif
#include <ao_aprs.h>
{
uint8_t i, bit, value;
- for (i = 0; i < length; ++i)
+ for (i = 0; i < length; ++i)
{
value = buffer[i];
- for (bit = 0; bit < 8; ++bit)
+ for (bit = 0; bit < 8; ++bit)
{
crc ^= (value & 0x01);
crc = ( crc & 0x01 ) ? ( crc >> 1 ) ^ 0x8408 : ( crc >> 1 );
/// AX.25 compliant packet header that contains destination, station call sign, and path.
/// 0x76 for SSID-11, 0x78 for SSID-12
-static uint8_t TNC_AX25_HEADER[] = {
+static uint8_t TNC_AX25_HEADER[] = {
'A' << 1, 'P' << 1, 'A' << 1, 'M' << 1, ' ' << 1, ' ' << 1, 0x60,
'N' << 1, '0' << 1, 'C' << 1, 'A' << 1, 'L' << 1, 'L' << 1, 0x78,
'W' << 1, 'I' << 1, 'D' << 1, 'E' << 1, '2' << 1, ' ' << 1, 0x65,
#define TNC_CALLSIGN_OFF 7
#define TNC_CALLSIGN_LEN 6
+#define TNC_SSID_OFF 13
static void
tncSetCallsign(void)
}
for (; i < TNC_CALLSIGN_LEN; i++)
TNC_AX25_HEADER[TNC_CALLSIGN_OFF + i] = ' ' << 1;
+
+ /* Fill in the SSID with the low digit of the serial number */
+ TNC_AX25_HEADER[TNC_SSID_OFF] = 0x60 | ((ao_config.aprs_ssid & 0xf) << 1);
#endif
}
/// Buffer to hold the message portion of the AX.25 packet as we prepare it.
static uint8_t tncBuffer[TNC_BUFFER_SIZE];
-/**
+/**
* Initialize the TNC internal variables.
*/
static void tncInit()
else
timeNCOFreq = 0x3aab;
- switch (tncMode)
+ switch (tncMode)
{
case TNC_TX_READY:
// Generate a test signal alteranting between high and low tones.
else
tncTxBit = 0;
}
-
+
// When the flag is done, determine if we need to send more or data.
- if (++tncBitCount == 8)
+ if (++tncBitCount == 8)
{
tncBitCount = 0;
tncShift = 0x7e;
// Once we transmit x mS of flags, send the data.
// txDelay bytes * 8 bits/byte * 833uS/bit = x mS
- if (++tncIndex == TNC_TX_DELAY)
+ if (++tncIndex == TNC_TX_DELAY)
{
tncIndex = 0;
tncShift = TNC_AX25_HEADER[0];
case TNC_TX_HEADER:
// Determine if we have sent 5 ones in a row, if we have send a zero.
- if (tncBitStuff == 0x1f)
+ if (tncBitStuff == 0x1f)
{
if (tncTxBit == 0)
tncTxBit = 1;
tncTxBit = 0;
}
- // Save the data stream so we can determine if bit stuffing is
+ // Save the data stream so we can determine if bit stuffing is
// required on the next bit time.
tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;
// If all the bits were shifted, get the next byte.
- if (++tncBitCount == 8)
+ if (++tncBitCount == 8)
{
tncBitCount = 0;
// After the header is sent, then send the data.
- if (++tncIndex == sizeof(TNC_AX25_HEADER))
+ if (++tncIndex == sizeof(TNC_AX25_HEADER))
{
tncIndex = 0;
tncShift = tncBuffer[0];
case TNC_TX_DATA:
// Determine if we have sent 5 ones in a row, if we have send a zero.
- if (tncBitStuff == 0x1f)
+ if (tncBitStuff == 0x1f)
{
if (tncTxBit == 0)
tncTxBit = 1;
tncTxBit = 0;
}
- // Save the data stream so we can determine if bit stuffing is
+ // Save the data stream so we can determine if bit stuffing is
// required on the next bit time.
tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;
// If all the bits were shifted, get the next byte.
- if (++tncBitCount == 8)
+ if (++tncBitCount == 8)
{
tncBitCount = 0;
// If everything was sent, transmit closing flags.
- if (++tncIndex == tncLength)
+ if (++tncIndex == tncLength)
{
tncIndex = 0;
tncShift = 0x7e;
case TNC_TX_END:
// The variable tncShift contains the lastest data byte.
- // NRZI enocde the data stream.
+ // NRZI enocde the data stream.
if ((tncShift & 0x01) == 0x00) {
if (tncTxBit == 0)
tncTxBit = 1;
}
// If all the bits were shifted, get the next one.
- if (++tncBitCount == 8)
+ if (++tncBitCount == 8)
{
tncBitCount = 0;
tncShift = 0x7e;
-
+
// Transmit two closing flags.
- if (++tncIndex == 2)
+ if (++tncIndex == 2)
{
tncMode = TNC_TX_READY;
#ifdef AO_SENSE_MAIN
" M%d.%d"
#endif
+ " %d"
, ao_gps_locked(),
ao_num_sats(),
battery/10,
, main/10,
main%10
#endif
+ , ao_serial_number
);
#else
return sprintf((char *) buf,
if (ao_gps_data.flags & AO_GPS_VALID) {
latitude = ao_gps_data.latitude;
longitude = ao_gps_data.longitude;
- altitude = ao_gps_data.altitude;
+ altitude = AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data);
if (altitude < 0)
altitude = 0;
}
return l;
}
-/**
+/**
* Prepare an AX.25 data packet. Each time this method is called, it automatically
* rotates through 1 of 3 messages.
*
#define FOSC 32000000
+#define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id)
#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz)
#define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
+#define ao_radio_spi_send_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1120_SPI_BUS)
#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS)
}
static void
-ao_radio_burst_read_start (uint16_t addr)
+_ao_radio_burst_read_start (uint16_t addr)
{
uint8_t data[2];
uint8_t d;
addr);
d = 1;
}
- ao_radio_select();
- ao_radio_spi_send(data, d);
+
+ ao_radio_spi_send_sync(data, d);
}
static void
return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);
}
-#if 0
+#if CC1120_DEBUG
static uint8_t
ao_radio_status(void)
{
{
ao_radio_mcu_wake = 0;
ao_radio_marc_status = ao_radio_get_marc_status();
-
+
/* Anyt other than 'tx/rx finished' means an error occurred */
if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))
ao_radio_abort = 1;
ao_radio_idle(void)
{
for (;;) {
- uint8_t state = ao_radio_strobe(CC1120_SIDLE);
- if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE)
+ uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK;
+ if (state == CC1120_STATUS_STATE_IDLE)
break;
- if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_TX_FIFO_ERROR)
+ if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)
ao_radio_strobe(CC1120_SFTX);
+ if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR)
+ ao_radio_strobe(CC1120_SFRX);
}
/* Flush any pending TX bytes */
ao_radio_strobe(CC1120_SFTX);
}
/*
- * Packet deviation is 20.5kHz
+ * Packet deviation
*
* fdev = fosc >> 24 * (256 + dev_m) << dev_e
*
+ * Deviation for 38400 baud should be 20.5kHz:
+ *
* 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz
+ *
+ * Deviation for 9600 baud should be 5.125kHz:
+ *
+ * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz
+ *
+ * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
+ * cc115l can't do that, so we'll use 1.5kHz instead:
+ *
+ * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz
*/
-#define PACKET_DEV_E 5
-#define PACKET_DEV_M 80
+#define PACKET_DEV_M_384 80
+#define PACKET_DEV_E_384 5
+
+#define PACKET_DEV_M_96 80
+#define PACKET_DEV_E_96 3
+
+#define PACKET_DEV_M_24 137
+#define PACKET_DEV_E_24 1
/*
- * For our packet data, set the symbol rate to 38400 Baud
+ * For our packet data
*
* (2**20 + DATARATE_M) * 2 ** DATARATE_E
* Rdata = -------------------------------------- * fosc
* 2 ** 39
*
+ * Given the bit period of the baseband, T, the bandwidth of the
+ * baseband signal is B = 1/(2T). The overall bandwidth of the
+ * modulated signal is then Channel bandwidth = 2Δf + 2B.
+ *
+ * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
+ * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
+ * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
+ *
+ * Symbol rate 38400 Baud:
*
* DATARATE_M = 239914
* DATARATE_E = 9
+ * CHANBW = 79.4 (round to 100)
+ *
+ * Symbol rate 9600 Baud:
+ *
+ * DATARATE_M = 239914
+ * DATARATE_E = 7
+ * CHANBW = 19.9 (round to 20)
+ *
+ * Symbol rate 2400 Baud:
+ *
+ * DATARATE_M = 239914
+ * DATARATE_E = 5
+ * CHANBW = 5.0 (round to 8.0)
*/
-#define PACKET_DRATE_E 9
+
#define PACKET_DRATE_M 239914
+#define PACKET_DRATE_E_384 9
+
+/* 200 / 2 = 100 */
+#define PACKET_CHAN_BW_384 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
+ (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
+ (2 << CC1120_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_DRATE_E_96 7
+/* 200 / 10 = 20 */
+#define PACKET_CHAN_BW_96 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
+ (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
+ (10 << CC1120_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_DRATE_E_24 5
+/* 200 / 25 = 8 */
+#define PACKET_CHAN_BW_24 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \
+ (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \
+ (25 << CC1120_CHAN_BW_BB_CIC_DECFACT))
+
static const uint16_t packet_setup[] = {
- CC1120_DEVIATION_M, PACKET_DEV_M,
- CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
- (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
- (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)),
- CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) |
- (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff),
CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff),
CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,
};
+static const uint16_t packet_setup_384[] = {
+ CC1120_DEVIATION_M, PACKET_DEV_M_384,
+ CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
+ (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)),
+ CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) |
+ (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
+ CC1120_CHAN_BW, PACKET_CHAN_BW_384,
+ CC1120_PA_CFG0, 0x7b,
+};
+
+static const uint16_t packet_setup_96[] = {
+ CC1120_DEVIATION_M, PACKET_DEV_M_96,
+ CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
+ (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)),
+ CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) |
+ (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
+ CC1120_CHAN_BW, PACKET_CHAN_BW_96,
+ CC1120_PA_CFG0, 0x7d,
+};
+
+static const uint16_t packet_setup_24[] = {
+ CC1120_DEVIATION_M, PACKET_DEV_M_24,
+ CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) |
+ (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)),
+ CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) |
+ (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),
+ CC1120_CHAN_BW, PACKET_CHAN_BW_24,
+ CC1120_PA_CFG0, 0x7e,
+};
+
static const uint16_t packet_tx_setup[] = {
CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |
(CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)),
(0 << CC1120_PKT_CFG0_UART_SWAP_EN)),
CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
(CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
+ CC1120_PA_CFG0, 0x7e,
};
/*
(0 << CC1120_PKT_CFG1_APPEND_STATUS)),
CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
(CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)),
+ CC1120_PA_CFG0, 0x7d,
};
/*
#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
#define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
+static void
+_ao_radio_set_regs(const uint16_t *regs, int nreg)
+{
+ int i;
+
+ for (i = 0; i < nreg; i++) {
+ ao_radio_reg_write(regs[0], regs[1]);
+ regs += 2;
+ }
+}
+
+#define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
+
static void
ao_radio_set_mode(uint16_t new_mode)
{
uint16_t changes;
- unsigned int i;
if (new_mode == ao_radio_mode)
return;
changes = new_mode & (~ao_radio_mode);
- if (changes & AO_RADIO_MODE_BITS_PACKET)
- for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
- ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
+
+ if (changes & AO_RADIO_MODE_BITS_PACKET) {
+ ao_radio_set_regs(packet_setup);
+
+ switch (ao_config.radio_rate) {
+ default:
+ case AO_RADIO_RATE_38400:
+ ao_radio_set_regs(packet_setup_384);
+ break;
+ case AO_RADIO_RATE_9600:
+ ao_radio_set_regs(packet_setup_96);
+ break;
+ case AO_RADIO_RATE_2400:
+ ao_radio_set_regs(packet_setup_24);
+ break;
+ }
+ }
if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
- for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2)
- ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]);
-
+ ao_radio_set_regs(packet_tx_setup);
+
if (changes & AO_RADIO_MODE_BITS_TX_BUF)
ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR);
ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);
if (changes & AO_RADIO_MODE_BITS_PACKET_RX)
- for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2)
- ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]);
-
+ ao_radio_set_regs(packet_rx_setup);
+
if (changes & AO_RADIO_MODE_BITS_RDF)
- for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
- ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
+ ao_radio_set_regs(rdf_setup);
if (changes & AO_RADIO_MODE_BITS_APRS)
- for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
- ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
+ ao_radio_set_regs(aprs_setup);
if (changes & AO_RADIO_MODE_BITS_TEST)
- for (i = 0; i < sizeof (test_setup) / sizeof (test_setup[0]); i += 2)
- ao_radio_reg_write(test_setup[i], test_setup[i+1]);
+ ao_radio_set_regs(test_setup);
if (changes & AO_RADIO_MODE_BITS_INFINITE)
ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE);
static void
ao_radio_setup(void)
{
- unsigned int i;
-
ao_radio_strobe(CC1120_SRES);
- for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
- ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
+ ao_radio_set_regs(radio_setup);
ao_radio_mode = 0;
ao_radio_get(uint8_t len)
{
static uint32_t last_radio_setting;
+ static uint8_t last_radio_rate;
ao_mutex_get(&ao_radio_mutex);
ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);
last_radio_setting = ao_config.radio_setting;
}
+ if (ao_config.radio_rate != last_radio_rate) {
+ ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
+ last_radio_rate = ao_config.radio_rate;
+ }
ao_radio_set_len(len);
}
ao_radio_set_mode(AO_RADIO_MODE_TEST);
ao_radio_strobe(CC1120_STX);
#if CC1120_TRACE
- { int t;
+ { int t;
for (t = 0; t < 10; t++) {
printf ("status: %02x\n", ao_radio_status());
ao_delay(AO_MS_TO_TICKS(100));
} else {
ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
}
-
+
fifo_space = ao_radio_wait_tx(encode_len != 0);
if (ao_radio_abort) {
ao_radio_idle();
static uint16_t rx_data_cur;
static uint8_t rx_ignore;
static uint8_t rx_waiting;
+static uint8_t rx_starting;
+static uint8_t rx_task_id;
+static uint32_t rx_fast_start;
+static uint32_t rx_slow_start;
+static uint32_t rx_missed;
#if AO_PROFILE
static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick;
{
uint8_t d;
+ if (rx_task_id) {
+ if (ao_radio_try_select(rx_task_id)) {
+ ++rx_fast_start;
+ rx_task_id = 0;
+ _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+ } else {
+ if (rx_ignore)
+ --rx_ignore;
+ else {
+ ao_radio_abort = 1;
+ rx_missed++;
+ }
+ return;
+ }
+ }
+ if (rx_starting) {
+ rx_starting = 0;
+ ao_wakeup(&ao_radio_wake);
+ }
d = AO_CC1120_SPI.dr;
AO_CC1120_SPI.dr = 0;
if (rx_ignore == 0) {
- if (rx_data_cur >= rx_data_count)
- ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
- else
+ if (rx_data_cur < rx_data_count)
rx_data[rx_data_cur++] = d;
+ if (rx_data_cur >= rx_data_count) {
+ ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN));
+ ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+ }
if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
#if AO_PROFILE
if (!rx_packet_tick)
static uint16_t
ao_radio_rx_wait(void)
{
- do {
- if (ao_radio_mcu_wake)
- ao_radio_check_marc_status();
- ao_alarm(AO_MS_TO_TICKS(100));
- ao_arch_block_interrupts();
- rx_waiting = 1;
- while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
- !ao_radio_abort &&
- !ao_radio_mcu_wake)
- {
- if (ao_sleep(&ao_radio_wake))
- ao_radio_abort = 1;
- }
- rx_waiting = 0;
- ao_arch_release_interrupts();
- ao_clear_alarm();
- } while (ao_radio_mcu_wake);
- if (ao_radio_abort)
+ ao_alarm(AO_MS_TO_TICKS(100));
+ ao_arch_block_interrupts();
+ rx_waiting = 1;
+ while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
+ !ao_radio_abort &&
+ !ao_radio_mcu_wake)
+ {
+ if (ao_sleep(&ao_radio_wake))
+ ao_radio_abort = 1;
+ }
+ rx_waiting = 0;
+ ao_arch_release_interrupts();
+ ao_clear_alarm();
+ if (ao_radio_abort || ao_radio_mcu_wake)
return 0;
rx_data_consumed += AO_FEC_DECODE_BLOCK;
#if AO_PROFILE
*/
ao_radio_abort = 0;
- /* configure interrupt pin */
ao_radio_get(len);
- ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
ao_radio_wake = 0;
ao_radio_mcu_wake = 0;
- AO_CC1120_SPI.cr2 = 0;
-
- /* clear any RXNE */
- (void) AO_CC1120_SPI.dr;
+ ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
- /* Have the radio signal when the preamble quality goes high */
- ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED);
+ /* configure interrupt pin */
+ ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
- AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
- ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr);
+ AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
+
+ ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
- ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN);
+
+ rx_starting = 1;
+ rx_task_id = ao_cur_task->task_id;
ao_radio_strobe(CC1120_SRX);
- /* Wait for the preamble to appear */
- ao_radio_wait_isr(timeout);
+ if (timeout)
+ ao_alarm(timeout);
+ ao_arch_block_interrupts();
+ while (rx_starting && !ao_radio_abort) {
+ if (ao_sleep(&ao_radio_wake))
+ ao_radio_abort = 1;
+ }
+ uint8_t rx_task_id_save = rx_task_id;
+ rx_task_id = 0;
+ rx_starting = 0;
+ ao_arch_release_interrupts();
+ if (timeout)
+ ao_clear_alarm();
+
if (ao_radio_abort) {
ret = 0;
+ rx_task_id = 0;
goto abort;
}
- ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);
- ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
- AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
-
- ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
- ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
-
- ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+ if (rx_task_id_save) {
+ ++rx_slow_start;
+ ao_radio_select();
+ _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
+ if (rx_ignore) {
+ uint8_t ignore = AO_CC1120_SPI.dr;
+ (void) ignore;
+ AO_CC1120_SPI.dr = 0;
+ --rx_ignore;
+ }
+ }
ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
ao_radio_burst_read_stop();
+ if (ao_radio_mcu_wake)
+ ao_radio_check_marc_status();
+ if (ao_radio_abort)
+ ret = 0;
+
abort:
/* Convert from 'real' rssi to cc1111-style values */
radio_rssi = AO_RADIO_FROM_RSSI (rssi);
}
- ao_radio_strobe(CC1120_SIDLE);
+ ao_radio_idle();
ao_radio_put();
char *name;
};
-const static struct ao_cc1120_reg ao_cc1120_reg[] = {
+static const struct ao_cc1120_reg ao_cc1120_reg[] = {
{ .addr = CC1120_IOCFG3, .name = "IOCFG3" },
{ .addr = CC1120_IOCFG2, .name = "IOCFG2" },
{ .addr = CC1120_IOCFG1, .name = "IOCFG1" },
static void ao_radio_show(void) {
uint8_t status = ao_radio_status();
- int i;
+ unsigned int i;
ao_radio_get(0xff);
status = ao_radio_status();
for (i = 0; i < AO_NUM_CC1120_REG; i++)
printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name);
+
+ printf("RX fast start: %u\n", rx_fast_start);
+ printf("RX slow start: %u\n", rx_slow_start);
+ printf("RX missed: %u\n", rx_missed);
ao_radio_put();
}
}
void
-ao_radio_test_recv()
+ao_radio_test_recv(void)
{
uint8_t bytes[34];
uint8_t b;
- if (ao_radio_recv(bytes, 34)) {
+ if (ao_radio_recv(bytes, 34, 0)) {
if (bytes[33] & 0x80)
printf ("CRC OK");
else
#include <ao_aprs.h>
static void
-ao_radio_aprs()
+ao_radio_aprs(void)
{
ao_packet_slave_stop();
ao_aprs_send();
}
#endif
-
#endif
static const struct ao_cmds ao_radio_cmds[] = {
#define CC1120_FREQ_IF_CFG 0x0f
#define CC1120_IQIC 0x10
#define CC1120_CHAN_BW 0x11
+#define CC1120_CHAN_BW_CHFILT_BYPASS 7
+#define CC1120_CHAN_BW_ADC_CIC_DECFACT 6
+#define CC1120_CHAN_BW_ADC_CIC_DECFACT_20 0
+#define CC1120_CHAN_BW_ADC_CIC_DECFACT_32 1
+#define CC1120_CHAN_BW_BB_CIC_DECFACT 0
+
#define CC1120_MDMCFG1 0x12
#define CC1120_MDMCFG1_CARRIER_SENSE_GATE 7
#define CC1120_MDMCFG1_FIFO_EN 6
#define CC1120_SETTLING_CFG_FS_AUTOCAL_MASK 3
#define CC1120_SETTLING_CFG_LOCK_TIME 1
#define CC1120_SETTLING_CFG_LOCK_TIME_50_20 0
-#define CC1120_SETTLING_CFG_LOCK_TIME_70_30 1
+#define CC1120_SETTLING_CFG_LOCK_TIME_75_30 1
#define CC1120_SETTLING_CFG_LOCK_TIME_100_40 2
#define CC1120_SETTLING_CFG_LOCK_TIME_150_60 3
#define CC1120_SETTLING_CFG_LOCK_TIME_MASK 3
CC1120_SYNC0, 0x91, /* Sync Word Configuration [7:0] */\r
\r
CC1120_SYNC_CFG1, /* Sync Word Detection Configuration */\r
- (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED << CC1120_SYNC_CFG1_DEM_CFG) |\r
- (0x07 << CC1120_SYNC_CFG1_SYNC_THR),\r
+ (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_DISABLED << CC1120_SYNC_CFG1_DEM_CFG) |\r
+ (0xc << CC1120_SYNC_CFG1_SYNC_THR),\r
CC1120_SYNC_CFG0,\r
(CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) |\r
- (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR),\r
- CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */\r
+ (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_DISABLED << CC1120_SYNC_CFG0_SYNC_NUM_ERROR),\r
+ CC1120_DCFILT_CFG, 0x15, /* Digital DC Removal Configuration */\r
CC1120_PREAMBLE_CFG1, /* Preamble Length Configuration */\r
(CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |\r
(CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD),\r
CC1120_PREAMBLE_CFG0,\r
- (1 << CC1120_PREAMBLE_CFG0_PQT_EN) |\r
- (0x6 << CC1120_PREAMBLE_CFG0_PQT),\r
- CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */\r
- CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */\r
+ (0 << CC1120_PREAMBLE_CFG0_PQT_EN) |\r
+ (0xe << CC1120_PREAMBLE_CFG0_PQT),\r
+\r
+ /* Adjust PQT lower to accept fewer packets */\r
+\r
+ CC1120_FREQ_IF_CFG, 0x3a, /* RX Mixer Frequency Configuration */\r
+ CC1120_IQIC, 0x00, /* Digital Image Channel Compensation Configuration */\r
CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */\r
\r
CC1120_MDMCFG1, /* General Modem Parameter Configuration */\r
(0 << CC1120_MDMCFG1_MANCHESTER_EN) |\r
(0 << CC1120_MDMCFG1_INVERT_DATA_EN) |\r
(0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) |\r
- (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) |\r
+ (CC1120_MDMCFG1_DVGA_GAIN_0 << CC1120_MDMCFG1_DVGA_GAIN) |\r
(0 << CC1120_MDMCFG1_SINGLE_ADC_EN),\r
- CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */\r
+ CC1120_MDMCFG0, 0x0d, /* General Modem Parameter Configuration */\r
\r
/* AGC reference = 10 * log10(receive BW) - 4 = 10 * log10(100e3) - 4 = 46 */\r
- CC1120_AGC_REF, 46, /* AGC Reference Level Configuration */\r
+ CC1120_AGC_REF, 0x36, /* AGC Reference Level Configuration */\r
\r
/* Carrier sense threshold - 25dB above the noise */\r
CC1120_AGC_CS_THR, 25, /* Carrier Sense Threshold Configuration */\r
\r
CC1120_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */\r
(CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) |\r
- (CC1120_SETTLING_CFG_LOCK_TIME_50_20 << CC1120_SETTLING_CFG_LOCK_TIME) |\r
+ (CC1120_SETTLING_CFG_LOCK_TIME_75_30 << CC1120_SETTLING_CFG_LOCK_TIME) |\r
(CC1120_SETTLING_CFG_FSREG_TIME_60 << CC1120_SETTLING_CFG_FSREG_TIME),\r
\r
CC1120_FS_CFG, /* Frequency Synthesizer Configuration */\r
CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */\r
CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */\r
#endif\r
- CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */\r
+ CC1120_RFEND_CFG1, 0x0e, /* RFEND Configuration, Reg 1 */\r
CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */\r
// CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */\r
CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */\r
CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */\r
CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */\r
CC1120_IF_MIX_CFG, 0x00, /* IF Mix Configuration */\r
- CC1120_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */\r
- CC1120_TOC_CFG, 0x0b, /* Timing Offset Correction Configuration */\r
+ CC1120_FREQOFF_CFG, 0x20, /* Frequency Offset Correction Configuration */\r
+ CC1120_TOC_CFG, 0x0a, /* Timing Offset Correction Configuration */\r
CC1120_MARC_SPARE, 0x00, /* MARC Spare */\r
CC1120_ECG_CFG, 0x00, /* External Clock Frequency Configuration */\r
CC1120_SOFT_TX_DATA_CFG, 0x00, /* Soft TX Data Configuration */\r
CC1120_XOSC4, 0xa0, /* Crystal Oscillator Configuration, Reg 4 */\r
CC1120_XOSC3, 0x03, /* Crystal Oscillator Configuration, Reg 3 */\r
CC1120_XOSC2, 0x04, /* Crystal Oscillator Configuration, Reg 2 */\r
- CC1120_XOSC1, 0x01, /* Crystal Oscillator Configuration, Reg 1 */\r
+ CC1120_XOSC1, 0x03, /* Crystal Oscillator Configuration, Reg 1 */\r
CC1120_XOSC0, 0x00, /* Crystal Oscillator Configuration, Reg 0 */\r
CC1120_ANALOG_SPARE, 0x00, /* */\r
CC1120_PA_CFG3, 0x00, /* Power Amplifier Configuration, Reg 3 */\r
CC1120_AGC_GAIN2, 0xd1, /* AGC Gain, Reg 2 */\r
CC1120_AGC_GAIN1, 0x00, /* AGC Gain, Reg 1 */\r
CC1120_AGC_GAIN0, 0x3f, /* AGC Gain, Reg 0 */\r
- CC1120_SOFT_RX_DATA_OUT, 0x00, /* Soft Decision Symbol Data */\r
- CC1120_SOFT_TX_DATA_IN, 0x00, /* Soft TX Data Input Register */\r
- CC1120_ASK_SOFT_RX_DATA, 0x30, /* AGC ASK Soft Decision Output */\r
CC1120_RNDGEN, 0x7f, /* Random Number Value */\r
- CC1120_MAGN2, 0x00, /* Signal Magnitude after CORDIC [16] */\r
- CC1120_MAGN1, 0x00, /* Signal Magnitude after CORDIC [15:8] */\r
- CC1120_MAGN0, 0x00, /* Signal Magnitude after CORDIC [7:0] */\r
- CC1120_ANG1, 0x00, /* Signal Angular after CORDIC [9:8] */\r
- CC1120_ANG0, 0x00, /* Signal Angular after CORDIC [7:0] */\r
- CC1120_CHFILT_I2, 0x08, /* Channel Filter Data Real Part [18:16] */\r
- CC1120_CHFILT_I1, 0x00, /* Channel Filter Data Real Part [15:8] */\r
- CC1120_CHFILT_I0, 0x00, /* Channel Filter Data Real Part [7:0] */\r
- CC1120_CHFILT_Q2, 0x00, /* Channel Filter Data Imaginary Part [18:16] */\r
- CC1120_CHFILT_Q1, 0x00, /* Channel Filter Data Imaginary Part [15:8] */\r
- CC1120_CHFILT_Q0, 0x00, /* Channel Filter Data Imaginary Part [7:0] */\r
- CC1120_GPIO_STATUS, 0x00, /* GPIO Status */\r
CC1120_FSCAL_CTRL, 0x01, /* */\r
CC1120_PHASE_ADJUST, 0x00, /* */\r
- CC1120_PARTNUMBER, 0x00, /* Part Number */\r
- CC1120_PARTVERSION, 0x00, /* Part Revision */\r
CC1120_SERIAL_STATUS, 0x00, /* Serial Status */\r
- CC1120_RX_STATUS, 0x01, /* RX Status */\r
- CC1120_TX_STATUS, 0x00, /* TX Status */\r
- CC1120_MARC_STATUS1, 0x00, /* MARC Status, Reg 1 */\r
- CC1120_MARC_STATUS0, 0x00, /* MARC Status, Reg 0 */\r
CC1120_PA_IFAMP_TEST, 0x00, /* */\r
CC1120_FSRF_TEST, 0x00, /* */\r
CC1120_PRE_TEST, 0x00, /* */\r
}
/*
- * Packet deviation is 20.5kHz
+ * Packet deviation
*
* fdev = fosc >> 17 * (8 + dev_m) << dev_e
*
+ * For 38400 baud, use 20.5kHz:
+ *
* 26e6 / (2 ** 17) * (8 + 5) * (2 ** 3) = 20630Hz
+ *
+ * For 9600 baud, use 5.125kHz:
+ *
+ * 26e6 / (2 ** 17) * (8 + 5) * (2 ** 1) = 5157Hz
+ *
+ * For 2400 baud, use 1.5kHz:
+ *
+ * 26e6 / (2 ** 17) * (8 + 0) * (2 ** 0) = 1587Hz
*/
-#define PACKET_DEV_E 3
-#define PACKET_DEV_M 5
+#define PACKET_DEV_E_384 3
+#define PACKET_DEV_M_384 5
+
+#define PACKET_DEV_E_96 1
+#define PACKET_DEV_M_96 5
+
+#define PACKET_DEV_E_24 0
+#define PACKET_DEV_M_24 0
/*
- * For our packet data, set the symbol rate to 38400 Baud
+ * For our packet data:
*
* (256 + DATARATE_M) * 2 ** DATARATE_E
* Rdata = -------------------------------------- * fosc
* 2 ** 28
*
+ * For 38400 baud:
+ *
* (256 + 131) * (2 ** 10) / (2**28) * 26e6 = 38383
*
* DATARATE_M = 131
- * DATARATE_E = 10
+ * DATARATE_E_384 = 10
+ * DATARATE_E_96 = 8
+ * DATARATE_E_24 = 6
*/
-#define PACKET_DRATE_E 10
-#define PACKET_DRATE_M 131
+#define PACKET_DRATE_M 131
+
+#define PACKET_DRATE_E_384 10
+#define PACKET_DRATE_E_96 8
+#define PACKET_DRATE_E_24 6
+
+static const struct {
+ uint8_t mdmcfg4;
+ uint8_t deviatn;
+} packet_rate_setup[] = {
+ [AO_RADIO_RATE_38400] = {
+ .mdmcfg4 = ((0xf << 4) |
+ (PACKET_DRATE_E_384 << CC115L_MDMCFG4_DRATE_E)),
+ .deviatn = ((PACKET_DEV_E_384 << CC115L_DEVIATN_DEVIATION_E) |
+ (PACKET_DEV_M_384 << CC115L_DEVIATN_DEVIATION_M)),
+ },
+
+ [AO_RADIO_RATE_9600] = {
+ .mdmcfg4 = ((0xf << 4) |
+ (PACKET_DRATE_E_96 << CC115L_MDMCFG4_DRATE_E)),
+ .deviatn = ((PACKET_DEV_E_96 << CC115L_DEVIATN_DEVIATION_E) |
+ (PACKET_DEV_M_96 << CC115L_DEVIATN_DEVIATION_M)),
+ },
+
+ [AO_RADIO_RATE_2400] = {
+ .mdmcfg4 = ((0xf << 4) |
+ (PACKET_DRATE_E_24 << CC115L_MDMCFG4_DRATE_E)),
+ .deviatn = ((PACKET_DEV_E_24 << CC115L_DEVIATN_DEVIATION_E) |
+ (PACKET_DEV_M_24 << CC115L_DEVIATN_DEVIATION_M)),
+ },
+};
static const uint16_t packet_setup[] = {
- CC115L_DEVIATN, ((PACKET_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
- (PACKET_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
- CC115L_MDMCFG4, ((0xf << 4) |
- (PACKET_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
CC115L_MDMCFG3, (PACKET_DRATE_M),
CC115L_MDMCFG2, (0x00 |
(CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
return;
changes = new_mode & (~ao_radio_mode);
- if (changes & AO_RADIO_MODE_BITS_PACKET_TX)
+ if (changes & AO_RADIO_MODE_BITS_PACKET_TX) {
+ ao_radio_reg_write(CC115L_MDMCFG4, packet_rate_setup[ao_config.radio_rate].mdmcfg4);
+ ao_radio_reg_write(CC115L_DEVIATN, packet_rate_setup[ao_config.radio_rate].deviatn);
+
for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
+ }
if (changes & AO_RADIO_MODE_BITS_RDF)
for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
ao_radio_get(void)
{
static uint32_t last_radio_setting;
+ static uint8_t last_radio_rate;
ao_mutex_get(&ao_radio_mutex);
if (!ao_radio_configured)
ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting);
last_radio_setting = ao_config.radio_setting;
}
+ if (ao_config.radio_rate != last_radio_rate) {
+ ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET_TX;
+ last_radio_rate = ao_config.radio_rate;
+ }
}
static void
ao_gps_lexchar();
i = ao_gps_decimal(0xff);
- if (i <= 50) {
- i = (uint8_t) 5 * i;
+ if (i <= 25) {
+ i = (uint8_t) 10 * i;
if (ao_gps_char == '.')
- i = (i + ((uint8_t) ao_gps_decimal(1) >> 1));
+ i = (i + ((uint8_t) ao_gps_decimal(1)));
} else
i = 255;
ao_gps_next.hdop = i;
ao_gps_skip_field();
- ao_gps_next.altitude = ao_gps_decimal(0xff);
+ AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_next, ao_gps_decimal(0xff));
+
ao_gps_skip_field(); /* skip any fractional portion */
ao_nmea_finish();
if (nav_timeutc.valid & (1 << NAV_TIMEUTC_VALID_UTC))
ao_gps_data.flags |= AO_GPS_DATE_VALID;
- ao_gps_data.altitude = nav_posllh.alt_msl / 1000;
+ AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_data, nav_posllh.alt_msl / 1000);
ao_gps_data.latitude = nav_posllh.lat;
ao_gps_data.longitude = nav_posllh.lon;
ao_gps_data.minute = nav_timeutc.min;
ao_gps_data.second = nav_timeutc.sec;
- ao_gps_data.pdop = nav_dop.pdop;
- ao_gps_data.hdop = nav_dop.hdop;
- ao_gps_data.vdop = nav_dop.vdop;
-
- /* mode is not set */
+ /* we report dop scaled by 10, but ublox provides dop scaled by 100
+ */
+ ao_gps_data.pdop = nav_dop.pdop / 10;
+ ao_gps_data.hdop = nav_dop.hdop / 10;
+ ao_gps_data.vdop = nav_dop.vdop / 10;
ao_gps_data.ground_speed = nav_velned.g_speed;
ao_gps_data.climb_rate = -nav_velned.vel_d;
{
int8_t r;
uint16_t sent_time;
+ uint16_t timeout = AO_MS_TO_TICKS(10);
+#if HAS_RADIO_RATE
+ switch (ao_config.radio_rate) {
+ case AO_RADIO_RATE_38400:
+ default:
+ break;
+ case AO_RADIO_RATE_9600:
+ timeout = AO_MS_TO_TICKS(20);
+ break;
+ case AO_RADIO_RATE_2400:
+ timeout = AO_MS_TO_TICKS(80);
+ break;
+ }
+#endif
ao_mutex_get(&ao_lco_mutex);
command.tick = ao_time() - *tick_offset;
command.box = box;
command.channels = 0;
ao_radio_cmac_send(&command, sizeof (command));
sent_time = ao_time();
- r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(10));
+ r = ao_radio_cmac_recv(query, sizeof (*query), timeout);
if (r == AO_RADIO_CMAC_OK)
*tick_offset = sent_time - query->tick;
ao_mutex_put(&ao_lco_mutex);
#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000)
#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000)
+#if HAS_RADIO_RATE
+#define AO_PACKET_MASTER_RECV_DELAY AO_MS_TO_TICKS(100) << (ao_config.radio_rate << 1)
+#else
+#define AO_PACKET_MASTER_RECV_DELAY AO_MS_TO_TICKS(100)
+#endif
+
static void
ao_packet_master_busy(void)
{
if (ao_tx_packet.len)
ao_packet_master_busy();
ao_packet_master_check_busy();
- ao_alarm(ao_packet_master_delay);
+ ao_alarm(AO_PACKET_MASTER_RECV_DELAY);
r = ao_packet_recv();
ao_clear_alarm();
if (r) {
void
ao_pad_manual(void)
{
+ uint8_t ignite;
+ int repeat;
ao_cmd_white();
if (!ao_match_word("DoIt"))
return;
ao_cmd_decimal();
if (ao_cmd_status != ao_cmd_success)
return;
- ao_pad_ignite = 1 << ao_cmd_lex_i;
- ao_wakeup(&ao_pad_ignite);
+ ignite = 1 << ao_cmd_lex_i;
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success) {
+ repeat = 1;
+ ao_cmd_status = ao_cmd_success;
+ } else
+ repeat = ao_cmd_lex_i;
+ while (repeat-- > 0) {
+ ao_pad_ignite = ignite;
+ ao_wakeup(&ao_pad_ignite);
+ ao_delay(AO_PAD_FIRE_TIME>>1);
+ }
}
static __xdata struct ao_task ao_pad_task;
+++ /dev/null
-ao_product.h
-easymega-*.elf
+++ /dev/null
-#
-# AltOS build
-#
-#
-
-include ../stm/Makefile.defs
-
-INC = \
- ao.h \
- ao_arch.h \
- ao_arch_funcs.h \
- ao_boot.h \
- ao_companion.h \
- ao_data.h \
- ao_sample.h \
- ao_pins.h \
- altitude-pa.h \
- ao_kalman.h \
- ao_product.h \
- ao_ms5607.h \
- ao_hmc5883.h \
- ao_mpu6000.h \
- ao_mma655x.h \
- ao_profile.h \
- ao_task.h \
- ao_whiten.h \
- ao_sample_profile.h \
- ao_quaternion.h \
- math.h \
- ao_mpu.h \
- stm32l.h \
- math.h \
- Makefile
-
-#
-# Common AltOS sources
-#
-# ao_hmc5883.c
-
-#PROFILE=ao_profile.c
-#PROFILE_DEF=-DAO_PROFILE=1
-
-#SAMPLE_PROFILE=ao_sample_profile.c \
-# ao_sample_profile_timer.c
-#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
-
-#STACK_GUARD=ao_mpu_stm.c
-#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
-
-MATH_SRC=\
- ef_acos.c \
- ef_sqrt.c \
- ef_rem_pio2.c \
- kf_cos.c \
- kf_sin.c \
- kf_rem_pio2.c \
- sf_copysign.c \
- sf_cos.c \
- sf_fabs.c \
- sf_floor.c \
- sf_scalbn.c \
- sf_sin.c \
- ef_log.c
-
-ALTOS_SRC = \
- ao_boot_chain.c \
- ao_interrupt.c \
- ao_product.c \
- ao_romconfig.c \
- ao_cmd.c \
- ao_config.c \
- ao_task.c \
- ao_led.c \
- ao_stdio.c \
- ao_panic.c \
- ao_timer.c \
- ao_mutex.c \
- ao_ignite.c \
- ao_freq.c \
- ao_dma_stm.c \
- ao_spi_stm.c \
- ao_data.c \
- ao_ms5607.c \
- ao_mma655x.c \
- ao_hmc5883.c \
- ao_adc_stm.c \
- ao_beep_stm.c \
- ao_eeprom_stm.c \
- ao_storage.c \
- ao_m25.c \
- ao_usb_stm.c \
- ao_exti_stm.c \
- ao_report.c \
- ao_i2c_stm.c \
- ao_mpu6000.c \
- ao_convert_pa.c \
- ao_convert_volt.c \
- ao_log.c \
- ao_log_mega.c \
- ao_sample.c \
- ao_kalman.c \
- ao_flight.c \
- ao_companion.c \
- ao_pyro.c \
- $(MATH_SRC) \
- $(PROFILE) \
- $(SAMPLE_PROFILE) \
- $(STACK_GUARD)
-
-PRODUCT=EasyMega-v0.1
-PRODUCT_DEF=-DEASYMEGA
-IDPRODUCT=0x0023
-
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
-
-PROGNAME=easymega-v0.1
-PROG=$(PROGNAME)-$(VERSION).elf
-HEX=$(PROGNAME)-$(VERSION).ihx
-
-SRC=$(ALTOS_SRC) ao_easymega.c
-OBJ=$(SRC:.c=.o)
-
-all: $(PROG) $(HEX)
-
-$(PROG): Makefile $(OBJ) altos.ld
- $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
-
-../altitude-pa.h: make-altitude-pa
- nickle $< > $@
-
-$(OBJ): $(INC)
-
-ao_product.h: ao-make-product.5c ../Version
- $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-distclean: clean
-
-clean:
- rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
- rm -f ao_product.h
-
-install:
-
-uninstall:
+++ /dev/null
-/*
- * Copyright © 2014 Bdale Garbee <bdale@gag.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao.h>
-#include <ao_hmc5883.h>
-#include <ao_mpu6000.h>
-#include <ao_mma655x.h>
-#include <ao_log.h>
-#include <ao_exti.h>
-#include <ao_companion.h>
-#include <ao_profile.h>
-#include <ao_eeprom.h>
-#if HAS_SAMPLE_PROFILE
-#include <ao_sample_profile.h>
-#endif
-#include <ao_pyro.h>
-#if HAS_STACK_GUARD
-#include <ao_mpu.h>
-#endif
-
-int
-main(void)
-{
- ao_clock_init();
-
-#if HAS_STACK_GUARD
- ao_mpu_init();
-#endif
-
- ao_task_init();
- ao_led_init(LEDS_AVAILABLE);
- ao_led_on(AO_LED_GREEN);
- ao_timer_init();
-
- ao_i2c_init();
- ao_spi_init();
- ao_dma_init();
- ao_exti_init();
-
- ao_adc_init();
-#if HAS_BEEP
- ao_beep_init();
-#endif
- ao_cmd_init();
-
-#if HAS_MS5607
- ao_ms5607_init();
-#endif
-#if HAS_HMC5883
- ao_hmc5883_init();
-#endif
-#if HAS_MPU6000
- ao_mpu6000_init();
-#endif
-#if HAS_MMA655X
- ao_mma655x_init();
-#endif
-
- ao_eeprom_init();
- ao_storage_init();
-
- ao_flight_init();
- ao_log_init();
- ao_report_init();
-
- ao_usb_init();
- ao_igniter_init();
- ao_companion_init();
- ao_pyro_init();
-
- ao_config_init();
-#if AO_PROFILE
- ao_profile_init();
-#endif
-#if HAS_SAMPLE_PROFILE
- ao_sample_profile_init();
-#endif
-
- ao_start_scheduler();
- return 0;
-}
+++ /dev/null
-/*
- * Copyright © 2014 Bdale Garbee <bdale@gag.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_PINS_H_
-#define _AO_PINS_H_
-
-#define HAS_TASK_QUEUE 1
-
-/* 8MHz High speed external crystal */
-#define AO_HSE 8000000
-
-/* PLLVCO = 96MHz (so that USB will work) */
-#define AO_PLLMUL 12
-#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
-
-/* SYSCLK = 32MHz (no need to go faster than CPU) */
-#define AO_PLLDIV 3
-#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
-
-/* HCLK = 32MHz (CPU clock) */
-#define AO_AHB_PRESCALER 1
-#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
-
-/* Run APB1 at 16MHz (HCLK/2) */
-#define AO_APB1_PRESCALER 2
-#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
-
-/* Run APB2 at 16MHz (HCLK/2) */
-#define AO_APB2_PRESCALER 2
-#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
-
-#define HAS_SERIAL_1 0
-#define USE_SERIAL_1_STDIN 0
-#define SERIAL_1_PB6_PB7 0
-#define SERIAL_1_PA9_PA10 0
-
-#define HAS_SERIAL_2 0
-#define USE_SERIAL_2_STDIN 0
-#define SERIAL_2_PA2_PA3 0
-#define SERIAL_2_PD5_PD6 0
-
-#define HAS_SERIAL_3 0
-#define USE_SERIAL_3_STDIN 0
-#define SERIAL_3_PB10_PB11 0
-#define SERIAL_3_PC10_PC11 0
-#define SERIAL_3_PD8_PD9 0
-
-#define ao_gps_getchar ao_serial1_getchar
-#define ao_gps_putchar ao_serial1_putchar
-#define ao_gps_set_speed ao_serial1_set_speed
-#define ao_gps_fifo (ao_stm_usart1.rx_fifo)
-
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024)
-#define HAS_EEPROM 1
-#define USE_INTERNAL_FLASH 0
-#define USE_EEPROM_CONFIG 1
-#define USE_STORAGE_CONFIG 0
-#define HAS_USB 1
-#define HAS_BEEP 1
-#define HAS_BATTERY_REPORT 1
-#define HAS_RADIO 0
-#define HAS_TELEMETRY 0
-#define HAS_APRS 0
-
-#define HAS_SPI_1 1
-#define SPI_1_PA5_PA6_PA7 1 /* Barometer */
-#define SPI_1_PB3_PB4_PB5 1 /* Accelerometer, Gyro */
-#define SPI_1_PE13_PE14_PE15 0
-#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
-
-#define HAS_SPI_2 1
-#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */
-#define SPI_2_PD1_PD3_PD4 0
-#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
-
-#define SPI_2_PORT (&stm_gpiob)
-#define SPI_2_SCK_PIN 13
-#define SPI_2_MISO_PIN 14
-#define SPI_2_MOSI_PIN 15
-
-#define HAS_I2C_1 1
-#define I2C_1_PB8_PB9 1
-
-#define HAS_I2C_2 0
-#define I2C_2_PB10_PB11 0
-
-#define PACKET_HAS_SLAVE 0
-#define PACKET_HAS_MASTER 0
-
-#define LOW_LEVEL_DEBUG 0
-
-#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOAEN
-#define LED_PORT (&stm_gpioa)
-#define LED_PIN_RED 9
-#define LED_PIN_GREEN 10
-#define AO_LED_RED (1 << LED_PIN_RED)
-#define AO_LED_GREEN (1 << LED_PIN_GREEN)
-
-#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
-
-#define HAS_GPS 0
-#define HAS_FLIGHT 1
-#define HAS_ADC 1
-#define HAS_ADC_TEMP 1
-#define HAS_LOG 1
-
-/*
- * Igniter
- */
-
-#define HAS_IGNITE 1
-#define HAS_IGNITE_REPORT 1
-
-#define AO_SENSE_PYRO(p,n) ((p)->adc.sense[n])
-#define AO_SENSE_DROGUE(p) ((p)->adc.sense[4])
-#define AO_SENSE_MAIN(p) ((p)->adc.sense[5])
-#define AO_IGNITER_CLOSED 400
-#define AO_IGNITER_OPEN 60
-
-/* Pyro A */
-#define AO_PYRO_PORT_0 (&stm_gpioa)
-#define AO_PYRO_PIN_0 15
-
-/* Pyro B */
-#define AO_PYRO_PORT_1 (&stm_gpioc)
-#define AO_PYRO_PIN_1 10
-
-/* Pyro C */
-#define AO_PYRO_PORT_2 (&stm_gpiob)
-#define AO_PYRO_PIN_2 11
-
-/* Pyro D */
-#define AO_PYRO_PORT_3 (&stm_gpiob)
-#define AO_PYRO_PIN_3 10
-
-/* Drogue */
-#define AO_IGNITER_DROGUE_PORT (&stm_gpioa)
-#define AO_IGNITER_DROGUE_PIN 0
-
-/* Main */
-#define AO_IGNITER_MAIN_PORT (&stm_gpioa)
-#define AO_IGNITER_MAIN_PIN 1
-
-/* Number of general purpose pyro channels available */
-#define AO_PYRO_NUM 4
-
-#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v)
-#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v)
-
-/*
- * ADC
- */
-#define AO_DATA_RING 32
-#define AO_ADC_NUM_SENSE 6
-
-struct ao_adc {
- int16_t sense[AO_ADC_NUM_SENSE];
- int16_t v_batt;
- int16_t v_pbatt;
- int16_t temp;
-};
-
-#define AO_ADC_DUMP(p) \
- printf("tick: %5u A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \
- (p)->tick, \
- (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \
- (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \
- (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp)
-
-#define AO_ADC_SENSE_A 14
-#define AO_ADC_SENSE_A_PORT (&stm_gpioc)
-#define AO_ADC_SENSE_A_PIN 4
-
-#define AO_ADC_SENSE_B 15
-#define AO_ADC_SENSE_B_PORT (&stm_gpioc)
-#define AO_ADC_SENSE_B_PIN 5
-
-#define AO_ADC_SENSE_C 13
-#define AO_ADC_SENSE_C_PORT (&stm_gpioc)
-#define AO_ADC_SENSE_C_PIN 3
-
-#define AO_ADC_SENSE_D 12
-#define AO_ADC_SENSE_D_PORT (&stm_gpioc)
-#define AO_ADC_SENSE_D_PIN 2
-
-#define AO_ADC_SENSE_DROGUE 11
-#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioc)
-#define AO_ADC_SENSE_DROGUE_PIN 1
-
-#define AO_ADC_SENSE_MAIN 10
-#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioc)
-#define AO_ADC_SENSE_MAIN_PIN 0
-
-#define AO_ADC_V_BATT 8
-#define AO_ADC_V_BATT_PORT (&stm_gpiob)
-#define AO_ADC_V_BATT_PIN 0
-
-#define AO_ADC_V_PBATT 9
-#define AO_ADC_V_PBATT_PORT (&stm_gpiob)
-#define AO_ADC_V_PBATT_PIN 1
-
-#define AO_ADC_TEMP 16
-
-#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \
- (1 << STM_RCC_AHBENR_GPIOEEN) | \
- (1 << STM_RCC_AHBENR_GPIOBEN))
-
-#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2)
-
-#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT
-#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN
-#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT
-#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN
-#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT
-#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN
-#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT
-#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN
-#define AO_ADC_PIN4_PORT AO_ADC_SENSE_DROGUE_PORT
-#define AO_ADC_PIN4_PIN AO_ADC_SENSE_DROGUE_PIN
-#define AO_ADC_PIN5_PORT AO_ADC_SENSE_MAIN_PORT
-#define AO_ADC_PIN5_PIN AO_ADC_SENSE_MAIN_PIN
-#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT
-#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN
-#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT
-#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN
-
-#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3)
-
-#define AO_ADC_SQ1 AO_ADC_SENSE_A
-#define AO_ADC_SQ2 AO_ADC_SENSE_B
-#define AO_ADC_SQ3 AO_ADC_SENSE_C
-#define AO_ADC_SQ4 AO_ADC_SENSE_D
-#define AO_ADC_SQ5 AO_ADC_SENSE_DROGUE
-#define AO_ADC_SQ6 AO_ADC_SENSE_MAIN
-#define AO_ADC_SQ7 AO_ADC_V_BATT
-#define AO_ADC_SQ8 AO_ADC_V_PBATT
-#define AO_ADC_SQ9 AO_ADC_TEMP
-
-/*
- * Voltage divider on ADC battery sampler
- */
-#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
-#define AO_BATTERY_DIV_MINUS 100 /* 10k */
-
-/*
- * Voltage divider on ADC igniter samplers
- */
-#define AO_IGNITE_DIV_PLUS 100 /* 100k */
-#define AO_IGNITE_DIV_MINUS 27 /* 27k */
-
-/*
- * ADC reference in decivolts
- */
-#define AO_ADC_REFERENCE_DV 33
-
-/*
- * Pressure sensor settings
- */
-#define HAS_MS5607 1
-#define HAS_MS5611 0
-#define AO_MS5607_PRIVATE_PINS 1
-#define AO_MS5607_CS_PORT (&stm_gpioa)
-#define AO_MS5607_CS_PIN 3
-#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN)
-#define AO_MS5607_MISO_PORT (&stm_gpioa)
-#define AO_MS5607_MISO_PIN 6
-#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN)
-#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7
-
-/*
- * SPI Flash memory
- */
-
-#define M25_MAX_CHIPS 1
-#define AO_M25_SPI_CS_PORT (&stm_gpiob)
-#define AO_M25_SPI_CS_PIN 12
-#define AO_M25_SPI_CS_MASK (1 << AO_M25_SPI_CS_PIN)
-#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15
-
-/*
- * Mag sensor (hmc5883)
- */
-
-#define HAS_HMC5883 1
-#define AO_HMC5883_INT_PORT (&stm_gpioc)
-#define AO_HMC5883_INT_PIN 14
-#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1)
-
-/*
- * mpu6000
- */
-
-#define HAS_MPU6000 1
-#define AO_MPU6000_INT_PORT (&stm_gpioc)
-#define AO_MPU6000_INT_PIN 15
-#define AO_MPU6000_SPI_BUS AO_SPI_1_PB3_PB4_PB5
-#define AO_MPU6000_SPI_CS_PORT (&stm_gpioc)
-#define AO_MPU6000_SPI_CS_PIN 13
-#define HAS_IMU 1
-
-/*
- * mma655x
- */
-
-#define HAS_MMA655X 1
-#define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
-#define AO_MMA655X_CS_PORT (&stm_gpioc)
-#define AO_MMA655X_CS_PIN 12
-
-#define NUM_CMDS 16
-
-/*
- * Companion
- */
-
-#define AO_COMPANION_CS_PORT (&stm_gpiob)
-#define AO_COMPANION_CS_PIN (6)
-#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15
-
-/*
- * Monitor
- */
-
-#define HAS_MONITOR 0
-#define LEGACY_MONITOR 0
-#define HAS_MONITOR_PUT 0
-#define AO_MONITOR_LED 0
-#define HAS_RSSI 0
-
-/*
- * Profiling Viterbi decoding
- */
-
-#ifndef AO_PROFILE
-#define AO_PROFILE 0
-#endif
-
-#endif /* _AO_PINS_H_ */
+++ /dev/null
-#
-# AltOS flash loader build
-#
-#
-
-TOPDIR=../..
-HARDWARE=easymega-v0.1
-include $(TOPDIR)/stm/Makefile-flash.defs
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_PINS_H_
-#define _AO_PINS_H_
-
-/* External crystal at 8MHz */
-#define AO_HSE 8000000
-
-#include <ao_flash_stm_pins.h>
-
-/* Companion port cs_companion0 PD0 */
-
-#define AO_BOOT_PIN 1
-#define AO_BOOT_APPLICATION_GPIO stm_gpiob
-#define AO_BOOT_APPLICATION_PIN 6
-#define AO_BOOT_APPLICATION_VALUE 1
-#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
-
-#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+easymega-*.elf
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_companion.h \
+ ao_data.h \
+ ao_sample.h \
+ ao_pins.h \
+ altitude-pa.h \
+ ao_kalman.h \
+ ao_product.h \
+ ao_ms5607.h \
+ ao_hmc5883.h \
+ ao_mpu6000.h \
+ ao_mma655x.h \
+ ao_profile.h \
+ ao_task.h \
+ ao_whiten.h \
+ ao_sample_profile.h \
+ ao_quaternion.h \
+ math.h \
+ ao_mpu.h \
+ stm32l.h \
+ math.h \
+ Makefile
+
+#
+# Common AltOS sources
+#
+# ao_hmc5883.c
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+# ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+MATH_SRC=\
+ ef_acos.c \
+ ef_sqrt.c \
+ ef_rem_pio2.c \
+ kf_cos.c \
+ kf_sin.c \
+ kf_rem_pio2.c \
+ sf_copysign.c \
+ sf_cos.c \
+ sf_fabs.c \
+ sf_floor.c \
+ sf_scalbn.c \
+ sf_sin.c \
+ ef_log.c
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_ignite.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_data.c \
+ ao_ms5607.c \
+ ao_mma655x.c \
+ ao_hmc5883.c \
+ ao_adc_stm.c \
+ ao_beep_stm.c \
+ ao_eeprom_stm.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_report.c \
+ ao_i2c_stm.c \
+ ao_mpu6000.c \
+ ao_convert_pa.c \
+ ao_convert_volt.c \
+ ao_log.c \
+ ao_log_mega.c \
+ ao_sample.c \
+ ao_kalman.c \
+ ao_flight.c \
+ ao_companion.c \
+ ao_pyro.c \
+ $(MATH_SRC) \
+ $(PROFILE) \
+ $(SAMPLE_PROFILE) \
+ $(STACK_GUARD)
+
+PRODUCT=EasyMega-v1.0
+PRODUCT_DEF=-DEASYMEGA
+IDPRODUCT=0x0028
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=easymega-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_easymega.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+../altitude-pa.h: make-altitude-pa
+ nickle $< > $@
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2014 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_hmc5883.h>
+#include <ao_mpu6000.h>
+#include <ao_mma655x.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_eeprom.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+
+int
+main(void)
+{
+ ao_clock_init();
+
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
+ ao_task_init();
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_GREEN);
+ ao_timer_init();
+
+ ao_i2c_init();
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_adc_init();
+#if HAS_BEEP
+ ao_beep_init();
+#endif
+ ao_cmd_init();
+
+#if HAS_MS5607
+ ao_ms5607_init();
+#endif
+#if HAS_HMC5883
+ ao_hmc5883_init();
+#endif
+#if HAS_MPU6000
+ ao_mpu6000_init();
+#endif
+#if HAS_MMA655X
+ ao_mma655x_init();
+#endif
+
+ ao_eeprom_init();
+ ao_storage_init();
+
+ ao_flight_init();
+ ao_log_init();
+ ao_report_init();
+
+ ao_usb_init();
+ ao_igniter_init();
+ ao_companion_init();
+ ao_pyro_init();
+
+ ao_config_init();
+#if AO_PROFILE
+ ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+ ao_sample_profile_init();
+#endif
+
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright © 2014 Bdale Garbee <bdale@gag.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE 1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PB6_PB7 0
+#define SERIAL_1_PA9_PA10 0
+
+#define HAS_SERIAL_2 0
+#define USE_SERIAL_2_STDIN 0
+#define SERIAL_2_PA2_PA3 0
+#define SERIAL_2_PD5_PD6 0
+
+#define HAS_SERIAL_3 0
+#define USE_SERIAL_3_STDIN 0
+#define SERIAL_3_PB10_PB11 0
+#define SERIAL_3_PC10_PC11 0
+#define SERIAL_3_PD8_PD9 0
+
+#define ao_gps_getchar ao_serial1_getchar
+#define ao_gps_putchar ao_serial1_putchar
+#define ao_gps_set_speed ao_serial1_set_speed
+#define ao_gps_fifo (ao_stm_usart1.rx_fifo)
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024)
+#define AO_CONFIG_MAX_SIZE 1024
+#define LOG_ERASE_MARK 0x55
+#define LOG_MAX_ERASE 128
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define HAS_BATTERY_REPORT 1
+#define HAS_RADIO 0
+#define HAS_TELEMETRY 0
+#define HAS_APRS 0
+
+#define HAS_SPI_1 1
+#define SPI_1_PA5_PA6_PA7 1 /* Barometer */
+#define SPI_1_PB3_PB4_PB5 1 /* Accelerometer, Gyro */
+#define SPI_1_PE13_PE14_PE15 0
+#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2 1
+#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define SPI_2_PORT (&stm_gpiob)
+#define SPI_2_SCK_PIN 13
+#define SPI_2_MISO_PIN 14
+#define SPI_2_MOSI_PIN 15
+
+#define HAS_I2C_1 1
+#define I2C_1_PB8_PB9 1
+
+#define HAS_I2C_2 0
+#define I2C_2_PB10_PB11 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT (&stm_gpioa)
+#define LED_PIN_RED 9
+#define LED_PIN_GREEN 10
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS 0
+#define HAS_FLIGHT 1
+#define HAS_ADC 1
+#define HAS_ADC_TEMP 1
+#define HAS_LOG 1
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE 1
+#define HAS_IGNITE_REPORT 1
+
+#define AO_SENSE_PYRO(p,n) ((p)->adc.sense[n])
+#define AO_SENSE_DROGUE(p) ((p)->adc.sense[4])
+#define AO_SENSE_MAIN(p) ((p)->adc.sense[5])
+#define AO_IGNITER_CLOSED 400
+#define AO_IGNITER_OPEN 60
+
+/* Pyro A */
+#define AO_PYRO_PORT_0 (&stm_gpioa)
+#define AO_PYRO_PIN_0 15
+
+/* Pyro B */
+#define AO_PYRO_PORT_1 (&stm_gpioc)
+#define AO_PYRO_PIN_1 10
+
+/* Pyro C */
+#define AO_PYRO_PORT_2 (&stm_gpiob)
+#define AO_PYRO_PIN_2 11
+
+/* Pyro D */
+#define AO_PYRO_PORT_3 (&stm_gpiob)
+#define AO_PYRO_PIN_3 10
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioa)
+#define AO_IGNITER_DROGUE_PIN 0
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT (&stm_gpioa)
+#define AO_IGNITER_MAIN_PIN 1
+
+/* Number of general purpose pyro channels available */
+#define AO_PYRO_NUM 4
+
+#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v)
+#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v)
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING 32
+#define AO_ADC_NUM_SENSE 6
+
+struct ao_adc {
+ int16_t sense[AO_ADC_NUM_SENSE];
+ int16_t v_batt;
+ int16_t v_pbatt;
+ int16_t temp;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5u A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \
+ (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \
+ (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp)
+
+#define AO_ADC_SENSE_A 14
+#define AO_ADC_SENSE_A_PORT (&stm_gpioc)
+#define AO_ADC_SENSE_A_PIN 4
+
+#define AO_ADC_SENSE_B 15
+#define AO_ADC_SENSE_B_PORT (&stm_gpioc)
+#define AO_ADC_SENSE_B_PIN 5
+
+#define AO_ADC_SENSE_C 13
+#define AO_ADC_SENSE_C_PORT (&stm_gpioc)
+#define AO_ADC_SENSE_C_PIN 3
+
+#define AO_ADC_SENSE_D 12
+#define AO_ADC_SENSE_D_PORT (&stm_gpioc)
+#define AO_ADC_SENSE_D_PIN 2
+
+#define AO_ADC_SENSE_DROGUE 11
+#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioc)
+#define AO_ADC_SENSE_DROGUE_PIN 1
+
+#define AO_ADC_SENSE_MAIN 10
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioc)
+#define AO_ADC_SENSE_MAIN_PIN 0
+
+#define AO_ADC_V_BATT 8
+#define AO_ADC_V_BATT_PORT (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN 0
+
+#define AO_ADC_V_PBATT 9
+#define AO_ADC_V_PBATT_PORT (&stm_gpiob)
+#define AO_ADC_V_PBATT_PIN 1
+
+#define AO_ADC_TEMP 16
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+ (1 << STM_RCC_AHBENR_GPIOEEN) | \
+ (1 << STM_RCC_AHBENR_GPIOBEN))
+
+#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2)
+
+#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT
+#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN
+#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT
+#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN
+#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT
+#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN
+#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT
+#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN
+#define AO_ADC_PIN4_PORT AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN4_PIN AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN5_PORT AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN5_PIN AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT
+#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN
+
+#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3)
+
+#define AO_ADC_SQ1 AO_ADC_SENSE_A
+#define AO_ADC_SQ2 AO_ADC_SENSE_B
+#define AO_ADC_SQ3 AO_ADC_SENSE_C
+#define AO_ADC_SQ4 AO_ADC_SENSE_D
+#define AO_ADC_SQ5 AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ6 AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ7 AO_ADC_V_BATT
+#define AO_ADC_SQ8 AO_ADC_V_PBATT
+#define AO_ADC_SQ9 AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS 100 /* 100k */
+#define AO_IGNITE_DIV_MINUS 27 /* 27k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607 1
+#define HAS_MS5611 0
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_CS_PORT (&stm_gpioa)
+#define AO_MS5607_CS_PIN 3
+#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN)
+#define AO_MS5607_MISO_PORT (&stm_gpioa)
+#define AO_MS5607_MISO_PIN 6
+#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN)
+#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpiob)
+#define AO_M25_SPI_CS_PIN 12
+#define AO_M25_SPI_CS_MASK (1 << AO_M25_SPI_CS_PIN)
+#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Mag sensor (hmc5883)
+ */
+
+#define HAS_HMC5883 1
+#define AO_HMC5883_INT_PORT (&stm_gpioc)
+#define AO_HMC5883_INT_PIN 14
+#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1)
+
+/*
+ * mpu6000
+ */
+
+#define HAS_MPU6000 1
+#define AO_MPU6000_INT_PORT (&stm_gpioc)
+#define AO_MPU6000_INT_PIN 15
+#define AO_MPU6000_SPI_BUS AO_SPI_1_PB3_PB4_PB5
+#define AO_MPU6000_SPI_CS_PORT (&stm_gpioc)
+#define AO_MPU6000_SPI_CS_PIN 13
+#define HAS_IMU 1
+
+/*
+ * mma655x
+ */
+
+#define HAS_MMA655X 1
+#define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
+#define AO_MMA655X_CS_PORT (&stm_gpioc)
+#define AO_MMA655X_CS_PIN 12
+
+#define NUM_CMDS 16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT (&stm_gpiob)
+#define AO_COMPANION_CS_PIN (6)
+#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR 0
+#define LEGACY_MONITOR 0
+#define HAS_MONITOR_PUT 0
+#define AO_MONITOR_LED 0
+#define HAS_RSSI 0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE 0
+#endif
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=easymega-v1.0
+include $(TOPDIR)/stm/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Companion port cs_companion0 PD0 */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
name = sprintf("%s_K%d_%d", prefix, i, time_inc);
else
name = sprintf("%s_K%d%d_%d", prefix, i, j, time_inc);
- printf ("#define %s to_fix32(%12.10f)\n", name, k[i,j]);
+ printf ("#define %s to_fix_k(%12.10f)\n", name, k[i,j]);
}
printf ("\n");
exit(0);
name = sprintf("%s_K%d_%d", prefix, i, time_inc);
else
name = sprintf("%s_K%d%d_%d", prefix, i, j, time_inc);
- printf ("#define %s to_fix32(%12.10f)\n", name, k[i,j]);
+ printf ("#define %s to_fix_k(%12.10f)\n", name, k[i,j]);
}
printf ("\n");
exit(0);
*/
#ifndef ao_mutex_get
+uint8_t
+ao_mutex_try(__xdata uint8_t *ao_mutex, uint8_t task_id) __reentrant;
+
void
ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant;
* Given raw data, convert to SI units
*/
+#if HAS_BARO
/* pressure from the sensor to altitude in meters */
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant;
+alt_t
+ao_pres_to_altitude(pres_t pres) __reentrant;
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant;
+pres_t
+ao_altitude_to_pres(alt_t alt) __reentrant;
int16_t
ao_temp_to_dC(int16_t temp) __reentrant;
+#endif
/*
* ao_convert_pa.c
#include <ao_data.h>
+#if HAS_BARO
alt_t
-ao_pa_to_altitude(int32_t pa);
+ao_pa_to_altitude(pres_t pa);
int32_t
ao_altitude_to_pa(alt_t alt);
+#endif
#if HAS_DBG
#include <ao_dbg.h>
#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000)
#endif
+void
+ao_telemetry_reset_interval(void);
+
void
ao_telemetry_set_interval(uint16_t interval);
#define HAS_RADIO_XMIT HAS_RADIO
#endif
+#define AO_RADIO_RATE_38400 0
+#define AO_RADIO_RATE_9600 1
+#define AO_RADIO_RATE_2400 2
+#define AO_RADIO_RATE_MAX AO_RADIO_RATE_2400
+
+#if defined(HAS_RADIO) && !defined(HAS_RADIO_RATE)
+#define HAS_RADIO_RATE HAS_RADIO
+#endif
+
void
ao_radio_general_isr(void) ao_arch_interrupt(16);
* ao_rssi.c
*/
+#ifdef AO_LED_TYPE
void
-ao_rssi_set(int rssi_value);
+ao_rssi_set(int16_t rssi_value);
void
-ao_rssi_init(uint8_t rssi_led);
+ao_rssi_init(AO_LED_TYPE rssi_led);
+#endif
/*
* ao_product.c
#endif
#if defined(AO_BOOT_APPLICATION_BASE) && defined(AO_BOOT_APPLICATION_BOUND)
"program-space %u\n"
+#endif
+#if AO_VALUE_32
+ "altitude-32 1\n"
#endif
, ao_manufacturer
, ao_product
#error Please define USE_INTERNAL_FLASH
#endif
#endif
+
#ifndef AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX
-#if USE_INTERNAL_FLASH
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config
-#else
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024)
-#endif
+# if FLIGHT_LOG_APPEND
+# define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_log_max
+# else
+# if USE_INTERNAL_FLASH
+# define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config
+# else
+# define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024)
+# endif
+# endif
#endif
+
#ifndef AO_CONFIG_DEFAULT_RADIO_POWER
#define AO_CONFIG_DEFAULT_RADIO_POWER 0x60
#endif
#define AO_CONFIG_DEFAULT_RADIO_AMP 0
+#define AO_CONFIG_DEFAULT_APRS_SSID (ao_serial_number % 10)
+#define AO_CONFIG_DEFAULT_RADIO_RATE AO_RADIO_RATE_38400
#if HAS_EEPROM
static void
#endif
#if HAS_RADIO
+
+#if HAS_RADIO_FORWARD
+__xdata uint32_t ao_send_radio_setting;
+#endif
+
void
ao_config_set_radio(void)
{
ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal);
+#if HAS_RADIO_FORWARD
+ ao_send_radio_setting = ao_freq_to_set(ao_config.send_frequency, ao_config.radio_cal);
+#endif
}
#endif /* HAS_RADIO */
#if AO_PYRO_NUM
if (minor < 18)
ao_config.pyro_time = AO_CONFIG_DEFAULT_PYRO_TIME;
+#endif
+#if HAS_APRS
+ if (minor < 19)
+ ao_config.aprs_ssid = AO_CONFIG_DEFAULT_APRS_SSID;
+#endif
+#if HAS_RADIO_RATE
+ if (minor < 20)
+ ao_config.radio_rate = AO_CONFIG_DEFAULT_RADIO_RATE;
+#endif
+#if HAS_RADIO_FORWARD
+ if (minor < 21)
+ ao_config.send_frequency = 434550;
#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
ao_radio_recv_abort();
#endif
}
+
+#endif
+
+#if HAS_RADIO_FORWARD
+void
+ao_config_send_frequency_show(void) __reentrant
+{
+ printf("Send frequency: %ld\n",
+ ao_config.send_frequency);
+}
+
+void
+ao_config_send_frequency_set(void) __reentrant
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.send_frequency = ao_cmd_lex_u32;
+ ao_config_set_radio();
+ _ao_config_edit_finish();
+#if HAS_RADIO_RECV
+ ao_radio_recv_abort();
+#endif
+}
+
#endif
#if HAS_FLIGHT
ao_config_set_radio();
_ao_config_edit_finish();
}
+
+#endif
+
+#if HAS_RADIO_RATE
+#ifndef HAS_TELEMETRY
+#error Please define HAS_TELEMETRY
+#endif
+
+void
+ao_config_radio_rate_show(void) __reentrant
+{
+ printf("Telemetry rate: %d\n", ao_config.radio_rate);
+}
+
+void
+ao_config_radio_rate_set(void) __reentrant
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ if (AO_RADIO_RATE_MAX < ao_cmd_lex_i) {
+ ao_cmd_status = ao_cmd_lex_error;
+ return;
+ }
+ _ao_config_edit_start();
+ ao_config.radio_rate = ao_cmd_lex_i;
+#if HAS_TELEMETRY
+ ao_telemetry_reset_interval();
+#endif
+ _ao_config_edit_finish();
+#if HAS_RADIO_RECV
+ ao_radio_recv_abort();
+#endif
+}
#endif
#if HAS_LOG
+
void
ao_config_log_show(void) __reentrant
{
printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10));
+#if FLIGHT_LOG_APPEND
+ printf("Log fixed: 1\n");
+#endif
}
+#if FLIGHT_LOG_APPEND
+void
+ao_config_log_fix_append(void)
+{
+ _ao_config_edit_start();
+ ao_config.flight_log_max = ao_storage_log_max;
+ _ao_config_edit_finish();
+ ao_mutex_get(&ao_config_mutex);
+ _ao_config_put();
+ ao_config_dirty = 0;
+ ao_mutex_put(&ao_config_mutex);
+}
+#endif
+
void
ao_config_log_set(void) __reentrant
{
+#if FLIGHT_LOG_APPEND
+ printf("Flight log fixed size %d kB\n", ao_storage_log_max >> 10);
+#else
uint16_t block = (uint16_t) (ao_storage_block >> 10);
uint16_t log_max = (uint16_t) (ao_storage_log_max >> 10);
ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10;
_ao_config_edit_finish();
}
+#endif
}
#endif /* HAS_LOG */
}
#endif
+#if HAS_APRS
+void
+ao_config_aprs_ssid_show(void)
+{
+ printf ("APRS SSID: %d\n",
+ ao_config.aprs_ssid);
+}
+
+void
+ao_config_aprs_ssid_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ if (15 < ao_cmd_lex_i) {
+ ao_cmd_status = ao_cmd_lex_error;
+ return;
+ }
+ _ao_config_edit_start();
+ ao_config.aprs_ssid = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+#endif /* HAS_APRS */
+
struct ao_config_var {
__code char *str;
void (*set)(void) __reentrant;
#if HAS_RADIO
{ "F <freq>\0Frequency (kHz)",
ao_config_frequency_set, ao_config_frequency_show },
+#if HAS_RADIO_FORWARD
+ { "R <freq>\0Repeater output frequency (kHz)",
+ ao_config_send_frequency_set, ao_config_send_frequency_show },
+#endif
{ "c <call>\0Callsign (8 char max)",
ao_config_callsign_set, ao_config_callsign_show },
{ "e <0 disable, 1 enable>\0Enable telemetry and RDF",
ao_config_radio_enable_set, ao_config_radio_enable_show },
{ "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",
ao_config_radio_cal_set, ao_config_radio_cal_show },
+#if HAS_RADIO_RATE
+ { "T <rate>\0Telemetry rate (0=38.4, 1=9.6, 2=2.4)",
+ ao_config_radio_rate_set, ao_config_radio_rate_show },
+#endif
#if HAS_RADIO_POWER
{ "p <setting>\0Radio power setting (0-255)",
ao_config_radio_power_set, ao_config_radio_power_show },
#if HAS_TRACKER
{ "t <motion> <interval>\0Tracker configuration",
ao_config_tracker_set, ao_config_tracker_show },
+#endif
+#if HAS_APRS
+ { "S <ssid>\0Set APRS SSID (0-15)",
+ ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
#endif
{ "s\0Show",
ao_config_show, 0 },
#define USE_EEPROM_CONFIG 0
#endif
+#ifndef FLIGHT_LOG_APPEND
+#define FLIGHT_LOG_APPEND 0
+#endif
+
#if USE_STORAGE_CONFIG
#include <ao_storage.h>
#endif
#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 18
+#define AO_CONFIG_MINOR 21
#define AO_AES_LEN 16
#if AO_PYRO_NUM
uint16_t pyro_time; /* minor version 18 */
#endif
+#if HAS_APRS
+ uint8_t aprs_ssid; /* minor version 19 */
+#endif
+#if HAS_RADIO_RATE
+ uint8_t radio_rate; /* minor version 20 */
+#endif
+#if HAS_RADIO_FORWARD
+ uint32_t send_frequency; /* minor version 21 */
+#endif
};
+#if HAS_RADIO_FORWARD
+extern __xdata uint32_t ao_send_radio_setting;
+#endif
+
#define AO_IGNITE_MODE_DUAL 0
#define AO_IGNITE_MODE_APOGEE 1
#define AO_IGNITE_MODE_MAIN 2
void
ao_config_set_radio(void);
+void
+ao_config_log_fix_append(void);
+
void
ao_config_init(void);
#include "ao.h"
#endif
-static const int16_t altitude_table[] = {
+#include <ao_sample.h>
+
+static const ao_v_t altitude_table[] = {
#include "altitude.h"
};
#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS)
#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1)
-int16_t
+ao_v_t
ao_pres_to_altitude(int16_t pres) __reentrant
{
uint8_t o;
#if AO_NEED_ALTITUDE_TO_PRES
int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant
+ao_altitude_to_pres(ao_v_t alt) __reentrant
{
- int16_t span, sub_span;
+ ao_v_t span, sub_span;
uint8_t l, h, m;
int32_t pres;
#endif
static const alt_t altitude_table[] AO_CONST_ATTRIB = {
+#if AO_SMALL_ALTITUDE_TABLE
+#include "altitude-pa-small.h"
+#else
#include "altitude-pa.h"
+#endif
};
#ifndef FETCH_ALT
#define ALT_MASK (ALT_SCALE - 1)
alt_t
-ao_pa_to_altitude(int32_t pa)
+ao_pa_to_altitude(pres_t pa)
{
int16_t o;
int16_t part;
- int32_t low, high;
+ alt_t low, high;
if (pa < 0)
pa = 0;
o = pa >> ALT_SHIFT;
part = pa & ALT_MASK;
- low = (int32_t) FETCH_ALT(o) * (ALT_SCALE - part);
- high = (int32_t) FETCH_ALT(o+1) * part + (ALT_SCALE >> 1);
+ low = (alt_t) FETCH_ALT(o) * (ALT_SCALE - part);
+ high = (alt_t) FETCH_ALT(o+1) * part + (ALT_SCALE >> 1);
return (low + high) >> ALT_SHIFT;
}
#ifdef AO_CONVERT_TEST
-int32_t
-ao_altitude_to_pa(int32_t alt)
+pres_t
+ao_altitude_to_pa(alt_t alt)
{
- int32_t span, sub_span;
+ alt_t span, sub_span;
uint16_t l, h, m;
int32_t pa;
}
span = altitude_table[l] - altitude_table[h];
sub_span = altitude_table[l] - alt;
- pa = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span;
+ pa = ((((alt_t) l * (span - sub_span) + (alt_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span;
if (pa > 120000)
pa = 120000;
if (pa < 0)
#include <stdint.h>
#define AO_CONVERT_TEST
typedef int32_t alt_t;
+typedef int32_t pres_t;
#include "ao_host.h"
#include "ao_convert_pa.c"
typedef int32_t pres_t;
-#ifndef AO_ALT_TYPE
#define AO_ALT_TYPE int32_t
-#endif
typedef AO_ALT_TYPE alt_t;
#endif
-#if !HAS_BARO
-typedef int16_t alt_t;
-#endif
-
/*
* Need a few macros to pull data from the sensors:
*
* resting
*/
static __data uint16_t ao_interval_end;
-static __data int16_t ao_interval_min_height;
-static __data int16_t ao_interval_max_height;
+static __data ao_v_t ao_interval_min_height;
+static __data ao_v_t ao_interval_max_height;
#if HAS_ACCEL
-static __data int16_t ao_coast_avg_accel;
+static __data ao_v_t ao_coast_avg_accel;
#endif
__pdata uint8_t ao_flight_force_idle;
}
#if HAS_FLIGHT_DEBUG
-static inline int int_part(int16_t i) { return i >> 4; }
-static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; }
+static inline int int_part(ao_v_t i) { return i >> 4; }
+static inline int frac_part(ao_v_t i) { return ((i & 0xf) * 100 + 8) / 16; }
static void
ao_flight_dump(void)
{
#if HAS_ACCEL
- int16_t accel;
+ ao_v_t accel;
accel = ((ao_config.accel_plus_g - ao_sample_accel) * ao_accel_scale) >> 16;
#endif
--- /dev/null
+/*
+ * 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_telem.h"
+
+static void
+ao_monitor_forward(void)
+{
+ uint32_t recv_radio_setting;
+ static __xdata struct ao_telemetry_all_recv packet;
+
+ for (;;) {
+ while (ao_monitoring)
+ ao_sleep(DATA_TO_XDATA(&ao_monitoring));
+
+ if (!ao_radio_recv(&packet, sizeof(packet), 0))
+ continue;
+ if (!(packet.status & PKT_APPEND_STATUS_1_CRC_OK))
+ continue;
+ recv_radio_setting = ao_config.radio_setting;
+ ao_config.radio_setting = ao_send_radio_setting;
+ ao_radio_send(&packet.telemetry, sizeof (packet.telemetry));
+ ao_config.radio_setting = recv_radio_setting;
+ }
+}
+
+static __xdata struct ao_task ao_monitor_forward_task;
+
+void
+ao_monitor_forward_init(void) __reentrant
+{
+ ao_add_task(&ao_monitor_forward_task, ao_monitor_forward, "monitor_forward");
+}
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FORWARD_H_
+#define _AO_FORWARD_H_
+
+void
+ao_monitor_forward_init(void) __reentrant;
+
+#endif /* _AO_FORWARD_H_ */
#endif
#include "ao_telem.h"
+#ifndef AO_TELEMETRY_LOCATION_ALTITUDE
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l) ((l)->altitude)
+#endif
+
void
ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant
{
AO_TELEM_GPS_ALTITUDE " %d ",
(long) gps_data->latitude,
(long) gps_data->longitude,
- gps_data->altitude);
+ AO_TELEMETRY_LOCATION_ALTITUDE(gps_data));
if (gps_data->flags & AO_GPS_DATE_VALID)
printf(AO_TELEM_GPS_YEAR " %d "
gps_log.u.gps_longitude = gps_data.longitude;
ao_log_data(&gps_log);
gps_log.type = AO_LOG_GPS_ALT;
- gps_log.u.gps_altitude.altitude = gps_data.altitude;
- gps_log.u.gps_altitude.unused = 0xffff;
+ gps_log.u.gps_altitude.altitude_low = gps_data.altitude_low;
+#if HAS_WIDE_GPS
+ gps_log.u.gps_altitude.altitude_high = gps_data.altitude_high;
+#else
+ gps_log.u.gps_altitude.altitude_high = 0xffff;
+#endif
ao_log_data(&gps_log);
if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {
gps_log.type = AO_LOG_GPS_DATE;
#if GPS_SPARSE_LOG
/* Don't log data if GPS has a fix and hasn't moved for a while */
if ((gps_data.flags & AO_GPS_VALID) &&
- !ao_gps_sparse_should_log(gps_data.latitude, gps_data.longitude, gps_data.altitude))
+ !ao_gps_sparse_should_log(gps_data.latitude, gps_data.longitude,
+ AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data))
continue;
#endif
if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) {
gps_log.type = AO_LOG_GPS_TIME;
gps_log.u.gps.latitude = gps_data.latitude;
gps_log.u.gps.longitude = gps_data.longitude;
- gps_log.u.gps.altitude = gps_data.altitude;
-
+ gps_log.u.gps.altitude_low = gps_data.altitude_low;
+ gps_log.u.gps.altitude_high = gps_data.altitude_high;
gps_log.u.gps.hour = gps_data.hour;
gps_log.u.gps.minute = gps_data.minute;
gps_log.u.gps.second = gps_data.second;
gps_log.type = AO_LOG_GPS_POS;
gps_log.u.gps.latitude = gps_data.latitude;
gps_log.u.gps.longitude = gps_data.longitude;
- gps_log.u.gps.altitude = gps_data.altitude;
+ gps_log.u.gps.altitude_low = gps_data.altitude_low;
+ gps_log.u.gps.altitude_high = gps_data.altitude_high;
ao_log_metrum(&gps_log);
gps_log.type = AO_LOG_GPS_TIME;
gps_log.u.gps_time.year = gps_data.year;
gps_log.u.gps_time.month = gps_data.month;
gps_log.u.gps_time.day = gps_data.day;
+ gps_log.u.gps_time.pdop = gps_data.pdop;
ao_log_metrum(&gps_log);
}
#include <ao.h>
#endif
+#include <ao_data.h>
+
void
ao_gps_show(void) __reentrant
{
printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day);
printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);
printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude);
- printf ("Alt: %d\n", ao_gps_data.altitude);
+#if HAS_WIDE_GPS
+ printf ("Alt: %ld\n", (long) AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data));
+#else
+ printf ("Alt: %d\n", AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data));
+#endif
printf ("Flags: 0x%x\n", ao_gps_data.flags);
printf ("Sats: %d", ao_gps_tracking_data.channels);
for (i = 0; i < ao_gps_tracking_data.channels; i++)
#include "ao_sample.h"
#include "ao_kalman.h"
+static __pdata ao_k_t ao_k_height;
+static __pdata ao_k_t ao_k_speed;
+static __pdata ao_k_t ao_k_accel;
-static __pdata int32_t ao_k_height;
-static __pdata int32_t ao_k_speed;
-static __pdata int32_t ao_k_accel;
+#define AO_K_STEP_100 to_fix_v(0.01)
+#define AO_K_STEP_2_2_100 to_fix_v(0.00005)
-#define AO_K_STEP_100 to_fix16(0.01)
-#define AO_K_STEP_2_2_100 to_fix16(0.00005)
+#define AO_K_STEP_10 to_fix_v(0.1)
+#define AO_K_STEP_2_2_10 to_fix_v(0.005)
-#define AO_K_STEP_10 to_fix16(0.1)
-#define AO_K_STEP_2_2_10 to_fix16(0.005)
+#define AO_K_STEP_1 to_fix_v(1)
+#define AO_K_STEP_2_2_1 to_fix_v(0.5)
-#define AO_K_STEP_1 to_fix16(1)
-#define AO_K_STEP_2_2_1 to_fix16(0.5)
+__pdata ao_v_t ao_height;
+__pdata ao_v_t ao_speed;
+__pdata ao_v_t ao_accel;
+__xdata ao_v_t ao_max_height;
+static __pdata ao_k_t ao_avg_height_scaled;
+__xdata ao_v_t ao_avg_height;
-__pdata int16_t ao_height;
-__pdata int16_t ao_speed;
-__pdata int16_t ao_accel;
-__xdata int16_t ao_max_height;
-static __pdata int32_t ao_avg_height_scaled;
-__xdata int16_t ao_avg_height;
-
-__pdata int16_t ao_error_h;
-__pdata int16_t ao_error_h_sq_avg;
+__pdata ao_v_t ao_error_h;
+__pdata ao_v_t ao_error_h_sq_avg;
#if HAS_ACCEL
-__pdata int16_t ao_error_a;
+__pdata ao_v_t ao_error_a;
#endif
static void
{
#ifdef AO_FLIGHT_TEST
if (ao_sample_tick - ao_sample_prev_tick > 50) {
- ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 +
- (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4;
- ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1;
+ ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_1 +
+ (ao_k_t) ao_accel * AO_K_STEP_2_2_1) >> 4;
+ ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_1;
return;
}
if (ao_sample_tick - ao_sample_prev_tick > 5) {
- ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 +
- (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4;
- ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10;
+ ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_10 +
+ (ao_k_t) ao_accel * AO_K_STEP_2_2_10) >> 4;
+ ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_10;
return;
}
if (ao_flight_debug) {
printf ("predict speed %g + (%g * %g) = %g\n",
ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0,
- (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0));
+ (ao_k_speed + (ao_k_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0));
}
#endif
- ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 +
- (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4;
- ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100;
+ ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_100 +
+ (ao_k_t) ao_accel * AO_K_STEP_2_2_100) >> 4;
+ ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_100;
}
static void
ao_kalman_err_height(void)
{
- int16_t e;
- int16_t height_distrust;
+ ao_v_t e;
+ ao_v_t height_distrust;
#if HAS_ACCEL
- int16_t speed_distrust;
+ ao_v_t speed_distrust;
#endif
- ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16);
+ ao_error_h = ao_sample_height - (ao_v_t) (ao_k_height >> 16);
e = ao_error_h;
if (e < 0)
#endif
if (height_distrust > 0x100)
height_distrust = 0x100;
- ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8);
+ ao_error_h = (ao_v_t) (((ao_k_t) ao_error_h * (0x100 - height_distrust)) >> 8);
#ifdef AO_FLIGHT_TEST
if (ao_flight_debug) {
printf("over height %g over speed %g distrust: %g height: error %d -> %d\n",
ao_kalman_err_height();
#ifdef AO_FLIGHT_TEST
if (ao_sample_tick - ao_sample_prev_tick > 50) {
- ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h;
- ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h;
- ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h;
+ ao_k_height += (ao_k_t) AO_BARO_K0_1 * ao_error_h;
+ ao_k_speed += (ao_k_t) AO_BARO_K1_1 * ao_error_h;
+ ao_k_accel += (ao_k_t) AO_BARO_K2_1 * ao_error_h;
return;
}
if (ao_sample_tick - ao_sample_prev_tick > 5) {
- ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h;
- ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h;
- ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h;
+ ao_k_height += (ao_k_t) AO_BARO_K0_10 * ao_error_h;
+ ao_k_speed += (ao_k_t) AO_BARO_K1_10 * ao_error_h;
+ ao_k_accel += (ao_k_t) AO_BARO_K2_10 * ao_error_h;
return;
}
#endif
- ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h;
- ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h;
- ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h;
+ ao_k_height += (ao_k_t) AO_BARO_K0_100 * ao_error_h;
+ ao_k_speed += (ao_k_t) AO_BARO_K1_100 * ao_error_h;
+ ao_k_accel += (ao_k_t) AO_BARO_K2_100 * ao_error_h;
}
#if HAS_ACCEL
static void
ao_kalman_err_accel(void)
{
- int32_t accel;
+ ao_k_t accel;
accel = (ao_config.accel_plus_g - ao_sample_accel) * ao_accel_scale;
(double) ao_error_h, AO_BOTH_K10_1 / 65536.0,
(double) ao_error_a, AO_BOTH_K11_1 / 65536.0,
(ao_k_speed +
- (int32_t) AO_BOTH_K10_1 * ao_error_h +
- (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0));
+ (ao_k_t) AO_BOTH_K10_1 * ao_error_h +
+ (ao_k_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0));
}
ao_k_height +=
- (int32_t) AO_BOTH_K00_1 * ao_error_h +
- (int32_t) AO_BOTH_K01_1 * ao_error_a;
+ (ao_k_t) AO_BOTH_K00_1 * ao_error_h +
+ (ao_k_t) AO_BOTH_K01_1 * ao_error_a;
ao_k_speed +=
- (int32_t) AO_BOTH_K10_1 * ao_error_h +
- (int32_t) AO_BOTH_K11_1 * ao_error_a;
+ (ao_k_t) AO_BOTH_K10_1 * ao_error_h +
+ (ao_k_t) AO_BOTH_K11_1 * ao_error_a;
ao_k_accel +=
- (int32_t) AO_BOTH_K20_1 * ao_error_h +
- (int32_t) AO_BOTH_K21_1 * ao_error_a;
+ (ao_k_t) AO_BOTH_K20_1 * ao_error_h +
+ (ao_k_t) AO_BOTH_K21_1 * ao_error_a;
return;
}
if (ao_sample_tick - ao_sample_prev_tick > 5) {
(double) ao_error_h, AO_BOTH_K10_10 / 65536.0,
(double) ao_error_a, AO_BOTH_K11_10 / 65536.0,
(ao_k_speed +
- (int32_t) AO_BOTH_K10_10 * ao_error_h +
- (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0));
+ (ao_k_t) AO_BOTH_K10_10 * ao_error_h +
+ (ao_k_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0));
}
ao_k_height +=
- (int32_t) AO_BOTH_K00_10 * ao_error_h +
- (int32_t) AO_BOTH_K01_10 * ao_error_a;
+ (ao_k_t) AO_BOTH_K00_10 * ao_error_h +
+ (ao_k_t) AO_BOTH_K01_10 * ao_error_a;
ao_k_speed +=
- (int32_t) AO_BOTH_K10_10 * ao_error_h +
- (int32_t) AO_BOTH_K11_10 * ao_error_a;
+ (ao_k_t) AO_BOTH_K10_10 * ao_error_h +
+ (ao_k_t) AO_BOTH_K11_10 * ao_error_a;
ao_k_accel +=
- (int32_t) AO_BOTH_K20_10 * ao_error_h +
- (int32_t) AO_BOTH_K21_10 * ao_error_a;
+ (ao_k_t) AO_BOTH_K20_10 * ao_error_h +
+ (ao_k_t) AO_BOTH_K21_10 * ao_error_a;
return;
}
if (ao_flight_debug) {
(double) ao_error_h, AO_BOTH_K10_100 / 65536.0,
(double) ao_error_a, AO_BOTH_K11_100 / 65536.0,
(ao_k_speed +
- (int32_t) AO_BOTH_K10_100 * ao_error_h +
- (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0));
+ (ao_k_t) AO_BOTH_K10_100 * ao_error_h +
+ (ao_k_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0));
}
#endif
ao_k_height +=
- (int32_t) AO_BOTH_K00_100 * ao_error_h +
- (int32_t) AO_BOTH_K01_100 * ao_error_a;
+ (ao_k_t) AO_BOTH_K00_100 * ao_error_h +
+ (ao_k_t) AO_BOTH_K01_100 * ao_error_a;
ao_k_speed +=
- (int32_t) AO_BOTH_K10_100 * ao_error_h +
- (int32_t) AO_BOTH_K11_100 * ao_error_a;
+ (ao_k_t) AO_BOTH_K10_100 * ao_error_h +
+ (ao_k_t) AO_BOTH_K11_100 * ao_error_a;
ao_k_accel +=
- (int32_t) AO_BOTH_K20_100 * ao_error_h +
- (int32_t) AO_BOTH_K21_100 * ao_error_a;
+ (ao_k_t) AO_BOTH_K20_100 * ao_error_h +
+ (ao_k_t) AO_BOTH_K21_100 * ao_error_a;
}
#else
ao_kalman_err_accel();
if (ao_sample_tick - ao_sample_prev_tick > 5) {
- ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a;
- ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a;
- ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a;
+ ao_k_height +=(ao_k_t) AO_ACCEL_K0_10 * ao_error_a;
+ ao_k_speed += (ao_k_t) AO_ACCEL_K1_10 * ao_error_a;
+ ao_k_accel += (ao_k_t) AO_ACCEL_K2_10 * ao_error_a;
return;
}
- ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a;
- ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a;
- ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a;
+ ao_k_height += (ao_k_t) AO_ACCEL_K0_100 * ao_error_a;
+ ao_k_speed += (ao_k_t) AO_ACCEL_K1_100 * ao_error_a;
+ ao_k_accel += (ao_k_t) AO_ACCEL_K2_100 * ao_error_a;
}
#endif /* else FORCE_ACCEL */
return max_flight;
}
-void
-ao_log_scan(void) __reentrant
+static void
+ao_log_erase(uint8_t slot) __reentrant
{
- uint8_t log_slot;
- uint8_t log_slots;
- uint8_t log_want;
+ uint32_t log_current_pos, log_end_pos;
- ao_config_get();
+ ao_log_erase_mark();
+ log_current_pos = ao_log_pos(slot);
+ log_end_pos = log_current_pos + ao_config.flight_log_max;
+ while (log_current_pos < log_end_pos) {
+ uint8_t i;
+ static __xdata uint8_t b;
+
+ /*
+ * Check to see if we've reached the end of
+ * the used memory to avoid re-erasing the same
+ * memory over and over again
+ */
+ for (i = 0; i < 16; i++) {
+ if (ao_storage_read(log_current_pos + i, &b, 1))
+ if (b != 0xff)
+ break;
+ }
+ if (i == 16)
+ break;
+ ao_storage_erase(log_current_pos);
+ log_current_pos += ao_storage_block;
+ }
+}
- ao_flight_number = ao_log_max_flight();
- if (ao_flight_number)
- if (++ao_flight_number == 0)
- ao_flight_number = 1;
+static void
+ao_log_find_max_erase_flight(void) __reentrant
+{
+ uint8_t log_slot;
/* Now look through the log of flight numbers from erase operations and
* see if the last one is bigger than what we found above
}
if (ao_flight_number == 0)
ao_flight_number = 1;
+}
+
+uint8_t
+ao_log_scan(void) __reentrant
+{
+ uint8_t log_slot;
+ uint8_t log_slots;
+#if FLIGHT_LOG_APPEND
+ uint8_t ret;
+#else
+ uint8_t log_want;
+#endif
+
+ ao_config_get();
+
+ /* Get any existing flight number */
+ ao_flight_number = ao_log_max_flight();
+
+#if FLIGHT_LOG_APPEND
+
+ /* Deal with older OS versions which stored multiple
+ * flights in rom by erasing everything after the first
+ * slot
+ */
+ if (ao_config.flight_log_max != ao_storage_log_max) {
+ log_slots = ao_log_slots();
+ for (log_slot = 1; log_slot < log_slots; log_slot++) {
+ if (ao_log_flight(log_slot) != 0)
+ ao_log_erase(log_slot);
+ }
+ ao_config_log_fix_append();
+ }
+ ao_log_current_pos = ao_log_pos(0);
+ ao_log_end_pos = ao_log_current_pos + ao_storage_log_max;
+
+ if (ao_flight_number) {
+ uint32_t full = ao_log_current_pos;
+ uint32_t empty = ao_log_end_pos - ao_log_size;
+
+ /* If there's already a flight started, then find the
+ * end of it
+ */
+ for (;;) {
+ ao_log_current_pos = (full + empty) >> 1;
+ ao_log_current_pos -= ao_log_current_pos % ao_log_size;
+
+ if (ao_log_current_pos == full) {
+ if (ao_log_check(ao_log_current_pos))
+ ao_log_current_pos += ao_log_size;
+ break;
+ }
+ if (ao_log_current_pos == empty)
+ break;
+
+ if (ao_log_check(ao_log_current_pos)) {
+ full = ao_log_current_pos;
+ } else {
+ empty = ao_log_current_pos;
+ }
+ }
+ ret = 1;
+ } else {
+ ao_log_find_max_erase_flight();
+ ret = 0;
+ }
+ ao_wakeup(&ao_flight_number);
+ return ret;
+#else
+
+ if (ao_flight_number)
+ if (++ao_flight_number == 0)
+ ao_flight_number = 1;
+
+ ao_log_find_max_erase_flight();
/* With a flight number in hand, find a place to write a new log,
* use the target flight number to index the available log slots so
if (++log_slot >= log_slots)
log_slot = 0;
} while (log_slot != log_want);
-
ao_wakeup(&ao_flight_number);
+ return 0;
+#endif
}
void
{
uint8_t slot;
uint8_t slots;
- uint32_t log_current_pos, log_end_pos;
ao_cmd_decimal();
if (ao_cmd_status != ao_cmd_success)
#if HAS_TRACKER
ao_tracker_erase_start(ao_cmd_lex_i);
#endif
- ao_log_erase_mark();
- log_current_pos = ao_log_pos(slot);
- log_end_pos = log_current_pos + ao_config.flight_log_max;
- while (log_current_pos < log_end_pos) {
- uint8_t i;
- static __xdata uint8_t b;
-
- /*
- * Check to see if we've reached the end of
- * the used memory to avoid re-erasing the same
- * memory over and over again
- */
- for (i = 0; i < 16; i++) {
- if (ao_storage_read(log_current_pos + i, &b, 1))
- if (b != 0xff)
- break;
- }
- if (i == 16)
- break;
- ao_storage_erase(log_current_pos);
- log_current_pos += ao_storage_block;
- }
+ ao_log_erase(slot);
#if HAS_TRACKER
ao_tracker_erase_end();
#endif
#define AO_LOG_FORMAT_NONE 127 /* No log at all */
extern __code uint8_t ao_log_format;
+extern __code uint8_t ao_log_size;
/* Return the flight number from the given log slot, 0 if none */
uint16_t
ao_log_flight(uint8_t slot);
+/* Check if there is valid log data at the specified location */
+uint8_t
+ao_log_check(uint32_t pos);
+
/* Flush the log */
void
ao_log_flush(void);
/* functions provided in ao_log.c */
/* Figure out the current flight number */
-void
+uint8_t
ao_log_scan(void) __reentrant;
/* Return the position of the start of the given log slot */
int32_t gps_latitude;
int32_t gps_longitude;
struct {
- int16_t altitude;
- uint16_t unused;
+ uint16_t altitude_low;
+ int16_t altitude_high;
} gps_altitude;
struct {
uint16_t svid;
struct {
int32_t latitude; /* 4 */
int32_t longitude; /* 8 */
- int16_t altitude; /* 12 */
+ uint16_t altitude_low; /* 12 */
uint8_t hour; /* 14 */
uint8_t minute; /* 15 */
uint8_t second; /* 16 */
uint8_t hdop; /* 27 */
uint8_t vdop; /* 28 */
uint8_t mode; /* 29 */
- } gps; /* 30 */
+ int16_t altitude_high; /* 30 */
+ } gps; /* 32 */
/* AO_LOG_GPS_SAT */
struct {
uint16_t channels; /* 4 */
} u;
};
+#define AO_LOG_MEGA_GPS_ALTITUDE(l) ((int32_t) ((l)->u.gps.altitude_high << 16) | ((l)->u.gps.altitude_low))
+#define AO_LOG_MEGA_SET_GPS_ALTITUDE(l,a) (((l)->u.gps.mode |= AO_GPS_MODE_ALTITUDE_24), \
+ ((l)->u.gps.altitude_high = (a) >> 16), \
+ (l)->u.gps.altitude_low = (a))
+
struct ao_log_metrum {
char type; /* 0 */
uint8_t csum; /* 1 */
struct {
int32_t latitude; /* 4 */
int32_t longitude; /* 8 */
- int16_t altitude; /* 12 */
- } gps; /* 14 */
+ uint16_t altitude_low; /* 12 */
+ int16_t altitude_high; /* 14 */
+ } gps; /* 16 */
/* AO_LOG_GPS_TIME */
struct {
uint8_t hour; /* 4 */
uint8_t year; /* 8 */
uint8_t month; /* 9 */
uint8_t day; /* 10 */
- uint8_t pad; /* 11 */
+ uint8_t pdop; /* 11 */
} gps_time; /* 12 */
/* AO_LOG_GPS_SAT (up to three packets) */
struct {
struct {
int32_t latitude; /* 4 */
int32_t longitude; /* 8 */
- int16_t altitude; /* 12 */
+ uint16_t altitude_low; /* 12 */
uint8_t hour; /* 14 */
uint8_t minute; /* 15 */
uint8_t second; /* 16 */
uint8_t hdop; /* 27 */
uint8_t vdop; /* 28 */
uint8_t mode; /* 29 */
- uint8_t state; /* 30 */
+ int16_t altitude_high; /* 30 */
} gps; /* 31 */
/* AO_LOG_GPS_SAT */
struct {
static __xdata struct ao_log_gps log;
__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEGPS;
+__code uint8_t ao_log_size = sizeof (struct ao_log_gps);
static uint8_t
ao_log_csum(__xdata uint8_t *b) __reentrant
log.type = AO_LOG_GPS_TIME;
log.u.gps.latitude = gps_data->latitude;
log.u.gps.longitude = gps_data->longitude;
- log.u.gps.altitude = gps_data->altitude;
+ log.u.gps.altitude_low = gps_data->altitude_low;
+ log.u.gps.altitude_high = gps_data->altitude_high;
log.u.gps.hour = gps_data->hour;
log.u.gps.minute = gps_data->minute;
return log.u.flight.flight;
return 0;
}
+
+uint8_t
+ao_log_check(uint32_t pos)
+{
+ if (!ao_storage_read(pos,
+ &log,
+ sizeof (struct ao_log_gps)))
+ return 0;
+
+ if (ao_log_dump_check_data())
+ return 1;
+ return 0;
+}
#ifndef _AO_LOG_GPS_H_
#define _AO_LOG_GPS_H_
-uint8_t
-ao_log_gps_should_log(int32_t lat, int32_t lon, int16_t alt);
-
void
ao_log_gps_flight(void);
static uint16_t ao_log_offset = STARTING_LOG_OFFSET;
+#define AO_LOG_ID_SHIFT 12
+#define AO_LOG_ID_MASK ((1 << AO_LOG_ID_SHIFT) - 1)
+
void
ao_log_micro_save(void)
{
uint16_t n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t);
+
+#if AO_LOG_ID
+ n_samples |= AO_LOG_ID << AO_LOG_ID_SHIFT;
+#endif
ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground));
ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min));
ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
uint16_t crc = 0xffff;
ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
+
if (n_samples == 0xffff)
n_samples = 0;
+#if AO_LOG_ID
+ n_samples &= AO_LOG_ID_MASK;
+#endif
nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples;
ao_async_start();
ao_async_byte('M');
ao_microflight(void)
{
int16_t sample_count;
+ int16_t log_count;
uint16_t time;
uint32_t pa_interval_min, pa_interval_max;
int32_t pa_diff;
- uint8_t h, i;
+ uint8_t h;
+ uint8_t i;
uint8_t accel_lock = 0;
uint32_t pa_sum = 0;
h = 0;
for (;;) {
time += SAMPLE_SLEEP;
+#if BOOST_DETECT
if ((sample_count & 0x1f) == 0)
ao_led_on(AO_LED_REPORT);
+#endif
ao_delay_until(time);
ao_microsample();
+#if BOOST_DETECT
if ((sample_count & 0x1f) == 0)
ao_led_off(AO_LED_REPORT);
+#endif
pa_hist[h] = pa;
h = SKIP_PA_HIST(h,1);
pa_diff = pa_ground - ao_pa;
+#if BOOST_DETECT
/* Check for a significant pressure change */
if (pa_diff > BOOST_DETECT)
break;
+#endif
if (sample_count < GROUND_AVG * 2) {
if (sample_count < GROUND_AVG)
pa_ground = pa_sum >> GROUND_AVG_SHIFT;
pa_sum = 0;
sample_count = 0;
+#if !BOOST_DETECT
+ break;
+#endif
}
}
}
/* Log the remaining samples so we get a complete history since leaving the ground */
- for (; i != h; i = SKIP_PA_HIST(i,2)) {
+#if LOG_INTERVAL < NUM_PA_HIST
+ for (; i != h; i = SKIP_PA_HIST(i,2))
+#endif
+ {
pa = pa_hist[i];
ao_log_micro_data();
}
/* Now sit around until the pressure is stable again and record the max */
sample_count = 0;
+ log_count = 0;
pa_min = ao_pa;
pa_interval_min = ao_pa;
pa_interval_max = ao_pa;
ao_microsample();
if ((sample_count & 3) == 0)
ao_led_off(AO_LED_REPORT);
- if (sample_count & 1)
+ if (log_count == LOG_INTERVAL - 1) {
ao_log_micro_data();
+ log_count = 0;
+ } else
+ log_count++;
/* If accelerating upwards, don't look for min pressure */
if (ao_pa_accel < ACCEL_LOCK_PA)
#define FIX_BITS 16
-#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
-#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
+#define to_fix_v(x) ((int16_t) ((x) * 65536.0 + 0.5))
+#define to_fix_k(x) ((int32_t) ((x) * 65536.0 + 0.5))
#define from_fix8(x) ((x) >> 8)
#define from_fix(x) ((x) >> 16)
-#define fix8_to_fix16(x) ((x) << 8)
+#define fix8_to_fix_v(x) ((x) << 8)
#define fix16_to_fix8(x) ((x) >> 8)
#include <ao_kalman.h>
/* Basic time step (96ms) */
-#define AO_MK_STEP to_fix16(0.096)
+#define AO_MK_STEP to_fix_v(0.096)
/* step ** 2 / 2 */
-#define AO_MK_STEP_2_2 to_fix16(0.004608)
+#define AO_MK_STEP_2_2 to_fix_v(0.004608)
uint32_t ao_k_pa; /* 24.8 fixed point */
int32_t ao_k_pa_speed; /* 16.16 fixed point */
{
ao_pa = pa;
ao_k_pa = pa << 8;
-}
+}
void
ao_microkalman_predict(void)
{
#if LEGACY_MONITOR
__xdata char callsign[AO_MAX_CALLSIGN+1];
+#endif
+#if LEGACY_MONITOR || HAS_RSSI
int16_t rssi;
#endif
uint8_t ao_monitor_tail;
hex(sum);
putchar ('\n');
#if HAS_RSSI
- if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) {
+ if (recv_raw.packet[ao_monitoring + 1] & AO_RADIO_STATUS_CRC_OK) {
rssi = AO_RSSI_FROM_RADIO(recv_raw.packet[ao_monitoring]);
ao_rssi_set(rssi);
}
#include "ao.h"
+#ifndef HAS_MUTEX_TRY
+#define HAS_MUTEX_TRY 1
+#endif
+
+#if HAS_MUTEX_TRY
+
+uint8_t
+ao_mutex_try(__xdata uint8_t *mutex, uint8_t task_id) __reentrant
+{
+ uint8_t ret;
+ if (*mutex == task_id)
+ ao_panic(AO_PANIC_MUTEX);
+ ao_arch_critical(
+ if (*mutex)
+ ret = 0;
+ else {
+ *mutex = task_id;
+ ret = 1;
+ });
+ return ret;
+}
+#endif
+
void
ao_mutex_get(__xdata uint8_t *mutex) __reentrant
{
uint16_t ao_pyro_fired;
+#ifndef PYRO_DBG
+#define PYRO_DBG 0
+#endif
+
+#if PYRO_DBG
+#define DBG(...) do { printf("\t%d: ", (int) (pyro - ao_config.pyro)); printf(__VA_ARGS__); } while (0)
+#else
+#define DBG(...)
+#endif
+
/*
* Given a pyro structure, figure out
* if the current flight state satisfies all
case ao_pyro_accel_less:
if (ao_accel <= pyro->accel_less)
continue;
+ DBG("accel %d > %d\n", ao_accel, pyro->accel_less);
break;
case ao_pyro_accel_greater:
if (ao_accel >= pyro->accel_greater)
continue;
+ DBG("accel %d < %d\n", ao_accel, pyro->accel_greater);
break;
-
-
case ao_pyro_speed_less:
if (ao_speed <= pyro->speed_less)
continue;
+ DBG("speed %d > %d\n", ao_speed, pyro->speed_less);
break;
case ao_pyro_speed_greater:
if (ao_speed >= pyro->speed_greater)
continue;
+ DBG("speed %d < %d\n", ao_speed, pyro->speed_greater);
break;
-
case ao_pyro_height_less:
if (ao_height <= pyro->height_less)
continue;
+ DBG("height %d > %d\n", ao_height, pyro->height_less);
break;
case ao_pyro_height_greater:
if (ao_height >= pyro->height_greater)
continue;
+ DBG("height %d < %d\n", ao_height, pyro->height_greater);
break;
#if HAS_GYRO
case ao_pyro_orient_less:
if (ao_sample_orient <= pyro->orient_less)
continue;
+ DBG("orient %d > %d\n", ao_sample_orient, pyro->orient_less);
break;
case ao_pyro_orient_greater:
if (ao_sample_orient >= pyro->orient_greater)
continue;
+ DBG("orient %d < %d\n", ao_sample_orient, pyro->orient_greater);
break;
#endif
case ao_pyro_time_less:
if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less)
continue;
+ DBG("time %d > %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_less);
break;
case ao_pyro_time_greater:
if ((int16_t) (ao_time() - ao_boost_tick) >= pyro->time_greater)
continue;
+ DBG("time %d < %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_greater);
break;
case ao_pyro_ascending:
if (ao_speed > 0)
continue;
+ DBG("not ascending speed %d\n", ao_speed);
break;
case ao_pyro_descending:
if (ao_speed < 0)
continue;
+ DBG("not descending speed %d\n", ao_speed);
break;
case ao_pyro_after_motor:
if (ao_motor_number == pyro->motor)
continue;
+ DBG("motor %d != %d\n", ao_motor_number, pyro->motor);
break;
case ao_pyro_delay:
case ao_pyro_state_less:
if (ao_flight_state < pyro->state_less)
continue;
+ DBG("state %d >= %d\n", ao_flight_state, pyro->state_less);
break;
case ao_pyro_state_greater_or_equal:
if (ao_flight_state >= pyro->state_greater_or_equal)
continue;
+ DBG("state %d >= %d\n", ao_flight_state, pyro->state_less);
break;
default:
struct ao_pyro *pyro;
uint8_t p, any_waiting;
uint16_t fire = 0;
-
+
any_waiting = 0;
for (p = 0; p < AO_PYRO_NUM; p++) {
pyro = &ao_config.pyro[p];
* the delay to expire
*/
if (pyro->delay_done) {
+
+ /* Check to make sure the required conditions
+ * remain valid. If not, inhibit the channel
+ * by setting the fired bit
+ */
+ if (!ao_pyro_ready(pyro)) {
+ pyro->fired = 1;
+ continue;
+ }
+
if ((int16_t) (ao_time() - pyro->delay_done) < 0)
continue;
}
printf ("invalid pyro channel %d\n", p);
return;
}
- pyro_tmp.flags = 0;
+ memset(&pyro_tmp, '\0', sizeof (pyro_tmp));
for (;;) {
ao_cmd_white();
if (ao_cmd_lex_c == '\n')
}
pyro_tmp.flags |= ao_pyro_values[v].flag;
if (ao_pyro_values[v].offset != NO_VALUE) {
+ uint8_t negative = 0;
+ ao_cmd_white();
+ if (ao_cmd_lex_c == '-') {
+ negative = 1;
+ ao_cmd_lex();
+ }
ao_cmd_decimal();
if (ao_cmd_status != ao_cmd_success)
return;
- if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE)
+ if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE) {
+ if (negative) {
+ ao_cmd_status = ao_cmd_syntax_error;
+ return;
+ }
*((uint8_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
- else
+ } else {
+ if (negative)
+ ao_cmd_lex_i = -ao_cmd_lex_i;
*((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
+ }
}
}
_ao_config_edit_start();
void
ao_pyro_manual(uint8_t p);
+enum ao_igniter_status
+ao_pyro_status(uint8_t p);
+
void
ao_pyro_print_status(void);
pause(AO_MS_TO_TICKS(100));
}
} else {
- c = 10;
+ c = 5;
while (c--) {
high(AO_MS_TO_TICKS(20));
low(AO_MS_TO_TICKS(20));
}
}
+#if AO_PYRO_NUM
+ pause(AO_MS_TO_TICKS(250));
+ for(c = 0; c < AO_PYRO_NUM; c++) {
+ enum ao_igniter_status status = ao_pyro_status(c);
+ if (status == ao_igniter_ready)
+ mid(AO_MS_TO_TICKS(25));
+ else
+ low(AO_MS_TO_TICKS(25));
+ pause(AO_MS_TO_TICKS(200));
+ }
+#endif
#if HAS_LOG
if (ao_log_full()) {
pause(AO_MS_TO_TICKS(100));
#include "ao.h"
-static __xdata uint16_t ao_rssi_time;
-static __pdata uint16_t ao_rssi_delay;
-static __pdata uint8_t ao_rssi_led;
+static __xdata uint16_t ao_rssi_time;
+static __pdata uint16_t ao_rssi_delay;
+static __pdata AO_LED_TYPE ao_rssi_led;
void
ao_rssi(void)
}
void
-ao_rssi_set(int rssi_value)
+ao_rssi_set(int16_t rssi_value)
{
if (rssi_value > 0)
rssi_value = 0;
__xdata struct ao_task ao_rssi_task;
void
-ao_rssi_init(uint8_t rssi_led)
+ao_rssi_init(AO_LED_TYPE rssi_led)
{
ao_rssi_led = rssi_led;
ao_rssi_delay = 0;
} else {
#if HAS_ACCEL
ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g;
- ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g;
+ ao_accel_scale = to_fix_32(GRAVITY * 2 * 16) / ao_accel_2g;
#endif
ao_sample_preflight_set();
ao_preflight = FALSE;
* ao_sample.c
*/
+#ifndef AO_VALUE_32
+#define AO_VALUE_32 1
+#endif
+
+#if AO_VALUE_32
+/*
+ * For 32-bit computed values, use 64-bit intermediates.
+ */
+typedef int64_t ao_k_t;
+typedef int32_t ao_v_t;
+#else
+/*
+ * For 16-bit computed values, use 32-bit intermediates.
+ */
+typedef int32_t ao_k_t;
+typedef int16_t ao_v_t;
+#endif
+
/*
* Barometer calibration
*
* 2047m/s² (over 200g)
*/
-#define AO_M_TO_HEIGHT(m) ((int16_t) (m))
-#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16))
-#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16))
+#define AO_M_TO_HEIGHT(m) ((ao_v_t) (m))
+#define AO_MS_TO_SPEED(ms) ((ao_v_t) ((ms) * 16))
+#define AO_MSS_TO_ACCEL(mss) ((ao_v_t) ((mss) * 16))
extern __pdata uint16_t ao_sample_tick; /* time of last data */
extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */
* ao_kalman.c
*/
-#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
-#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
+#define to_fix_16(x) ((int16_t) ((x) * 65536.0 + 0.5))
+#define to_fix_32(x) ((int32_t) ((x) * 65536.0 + 0.5))
+#define to_fix_64(x) ((int64_t) ((x) * 65536.0 + 0.5))
+
+#ifdef AO_VALUE_32
+#if AO_VALUE_32
+#define to_fix_v(x) to_fix_32(x)
+#define to_fix_k(x) to_fix_64(x)
+#else
+#define to_fix_v(x) to_fix_16(x)
+#define to_fix_k(x) to_fix_32(x)
+#endif
+
#define from_fix(x) ((x) >> 16)
-extern __pdata int16_t ao_height; /* meters */
-extern __pdata int16_t ao_speed; /* m/s * 16 */
-extern __pdata int16_t ao_accel; /* m/s² * 16 */
-extern __xdata int16_t ao_max_height; /* max of ao_height */
-extern __xdata int16_t ao_avg_height; /* running average of height */
+extern __pdata ao_v_t ao_height; /* meters */
+extern __pdata ao_v_t ao_speed; /* m/s * 16 */
+extern __pdata ao_v_t ao_accel; /* m/s² * 16 */
+extern __xdata ao_v_t ao_max_height; /* max of ao_height */
+extern __xdata ao_v_t ao_avg_height; /* running average of height */
-extern __pdata int16_t ao_error_h;
-extern __pdata int16_t ao_error_h_sq_avg;
+extern __pdata ao_v_t ao_error_h;
+extern __pdata ao_v_t ao_error_h_sq_avg;
#if HAS_ACCEL
-extern __pdata int16_t ao_error_a;
+extern __pdata ao_v_t ao_error_a;
+#endif
#endif
void ao_kalman(void);
/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ * Copyright © 2011 Keth Packard <keithp@keithp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
static __pdata uint16_t ao_telemetry_interval;
+#if HAS_RADIO_RATE
+static __xdata uint16_t ao_telemetry_desired_interval;
+#endif
+
#if HAS_RDF
static __pdata uint8_t ao_rdf = 0;
static __pdata uint16_t ao_rdf_time;
ao_send_sensor(void)
{
__xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)];
-
+
telemetry.generic.tick = packet->tick;
telemetry.generic.type = AO_TELEMETRY_SENSOR;
#ifdef AO_SEND_MEGA
+
/* Send mega sensor packet */
static void
ao_send_mega_sensor(void)
{
__xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)];
-
+
telemetry.generic.tick = packet->tick;
telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR;
ao_send_mini(void)
{
__xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)];
-
+
telemetry.generic.tick = packet->tick;
telemetry.generic.type = AO_TELEMETRY_MINI;
ao_mutex_get(&ao_gps_mutex);
ao_xmemcpy(&telemetry.location.flags,
&ao_gps_data.flags,
- 26);
+ 27);
telemetry.location.tick = ao_gps_tick;
ao_mutex_put(&ao_gps_mutex);
ao_radio_send(&telemetry, sizeof (telemetry));
}
}
+#if HAS_RADIO_RATE
+void
+ao_telemetry_reset_interval(void)
+{
+ ao_telemetry_set_interval(ao_telemetry_desired_interval);
+}
+#endif
+
void
ao_telemetry_set_interval(uint16_t interval)
{
int8_t cur = 0;
+
+#if HAS_RADIO_RATE
+ /* Limit max telemetry rate based on available radio bandwidth.
+ */
+ static __xdata const uint16_t min_interval[] = {
+ /* [AO_RADIO_RATE_38400] = */ AO_MS_TO_TICKS(100),
+ /* [AO_RADIO_RATE_9600] = */ AO_MS_TO_TICKS(500),
+ /* [AO_RADIO_RATE_2400] = */ AO_MS_TO_TICKS(1000)
+ };
+
+ ao_telemetry_desired_interval = interval;
+ if (interval < min_interval[ao_config.radio_rate])
+ interval = min_interval[ao_config.radio_rate];
+#endif
ao_telemetry_interval = interval;
-
#if AO_SEND_MEGA
if (interval > 1)
ao_telemetry_mega_data_max = 1;
ao_telemetry_companion_cur = cur;
#endif
- ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval;
+ ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval;
#if HAS_COMPANION
if (ao_telemetry_config_max > cur)
cur++;
#define AO_TELEMETRY_LOCATION 0x05
-#define AO_GPS_MODE_NOT_VALID 'N'
-#define AO_GPS_MODE_AUTONOMOUS 'A'
-#define AO_GPS_MODE_DIFFERENTIAL 'D'
-#define AO_GPS_MODE_ESTIMATED 'E'
-#define AO_GPS_MODE_MANUAL 'M'
-#define AO_GPS_MODE_SIMULATED 'S'
+/* Mode bits */
+
+#define AO_GPS_MODE_ALTITUDE_24 (1 << 0) /* reports 24-bits of altitude */
struct ao_telemetry_location {
uint16_t serial; /* 0 */
uint8_t type; /* 4 */
uint8_t flags; /* 5 Number of sats and other flags */
- int16_t altitude; /* 6 GPS reported altitude (m) */
+ uint16_t altitude_low; /* 6 GPS reported altitude (m) */
int32_t latitude; /* 8 latitude (degrees * 10⁷) */
int32_t longitude; /* 12 longitude (degrees * 10⁷) */
uint8_t year; /* 16 (- 2000) */
uint16_t ground_speed; /* 26 cm/s */
int16_t climb_rate; /* 28 cm/s */
uint8_t course; /* 30 degrees / 2 */
- uint8_t unused; /* 31 unused */
+ int8_t altitude_high; /* 31 high byte of altitude */
/* 32 */
};
+#if HAS_GPS
+
+#ifndef HAS_WIDE_GPS
+#define HAS_WIDE_GPS 1
+#endif
+
+#if HAS_WIDE_GPS
+typedef int32_t gps_alt_t;
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l) (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low))
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->mode |= AO_GPS_MODE_ALTITUDE_24), \
+ ((l)->altitude_high = (a) >> 16), \
+ ((l)->altitude_low = (a)))
+#else
+typedef int16_t gps_alt_t;
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l) ((gps_alt_t) (l)->altitude_low)
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->mode = 0, \
+ (l)->altitude_low = (a)))
+#endif /* HAS_WIDE_GPS */
+
+#endif /* HAS_GPS */
+
#define AO_TELEMETRY_SATELLITE 0x06
struct ao_telemetry_satellite_info {
#endif
struct gps_position {
- int32_t latitude;
- int32_t longitude;
- int16_t altitude;
+ int32_t latitude;
+ int32_t longitude;
+ gps_alt_t altitude;
};
#define GPS_RING 16
#if !HAS_USB_CONNECT
ao_tracker_force_telem = 1;
#endif
- ao_log_scan();
+ log_started = ao_log_scan();
ao_rdf_set(1);
{
uint8_t ring;
uint8_t moving = 0;
+ gps_alt_t altitude = AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data);
for (ring = ao_gps_ring_next(gps_head); ring != gps_head; ring = ao_gps_ring_next(ring)) {
ground_distance = ao_distance(gps_data.latitude, gps_data.longitude,
gps_position[ring].latitude,
gps_position[ring].longitude);
- height = gps_position[ring].altitude - gps_data.altitude;
+ height = gps_position[ring].altitude - altitude;
if (height < 0)
height = -height;
ao_log_gps_data(gps_tick, &gps_data);
gps_position[gps_head].latitude = gps_data.latitude;
gps_position[gps_head].longitude = gps_data.longitude;
- gps_position[gps_head].altitude = gps_data.altitude;
+ gps_position[gps_head].altitude = altitude;
gps_head = ao_gps_ring_next(gps_head);
ao_mutex_put(&tracker_mutex);
}
ao_tracker_erase_end(void)
{
if (erasing_current) {
- ao_log_scan();
- log_started = 0;
+ log_started = ao_log_scan();
ao_mutex_put(&tracker_mutex);
}
}
printf ("log_started: %d\n", log_started);
printf ("latitude: %ld\n", (long) gps_data.latitude);
printf ("longitude: %ld\n", (long) gps_data.longitude);
- printf ("altitude: %d\n", gps_data.altitude);
+ printf ("altitude: %ld\n", AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data));
printf ("log_running: %d\n", ao_log_running);
printf ("log_start_pos: %ld\n", (long) ao_log_start_pos);
printf ("log_cur_pos: %ld\n", (long) ao_log_current_pos);
#endif /* HAS_TASK */
-#define ao_arch_wait_interrupt() do { \
- asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \
- ao_arch_release_interrupts(); \
- ao_arch_block_interrupts(); \
+#define ao_arch_wait_interrupt() do { \
+ asm("\twfi\n"); \
+ ao_arch_release_interrupts(); \
+ asm(".global ao_idle_loc\n\nao_idle_loc:"); \
+ ao_arch_block_interrupts(); \
} while (0)
-#define ao_arch_critical(b) do { \
- ao_arch_block_interrupts(); \
- do { b } while (0); \
- ao_arch_release_interrupts(); \
+#define ao_arch_critical(b) do { \
+ uint32_t __mask = ao_arch_irqsave(); \
+ do { b } while (0); \
+ ao_arch_irqrestore(__mask); \
} while (0)
/*
ao_rssi.c \
ao_send_packet.c \
ao_packet_master.c \
+ ao_eeprom_stm.c \
ao_packet.c
PRODUCT=MegaDongle-v0.1
main(void)
{
ao_clock_init();
-
+
#if HAS_STACK_GUARD
ao_mpu_init();
#endif
ao_send_packet_init();
ao_config_init();
-
+
ao_start_scheduler();
return 0;
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
+/* Using TeleMetrum v1.9 board */
+
#ifndef _AO_PINS_H_
#define _AO_PINS_H_
#define HAS_SERIAL_1 0
#define USE_SERIAL_1_STDIN 0
#define SERIAL_1_PB6_PB7 0
-#define SERIAL_1_PA9_PA10 1
+#define SERIAL_1_PA9_PA10 0
#define HAS_SERIAL_2 0
#define USE_SERIAL_2_STDIN 0
#define HAS_SERIAL_3 0
#define USE_SERIAL_3_STDIN 0
#define SERIAL_3_PB10_PB11 0
-#define SERIAL_3_PC10_PC11 1
+#define SERIAL_3_PC10_PC11 0
#define SERIAL_3_PD8_PD9 0
-#define ao_gps_getchar ao_serial3_getchar
-#define ao_gps_putchar ao_serial3_putchar
-#define ao_gps_set_speed ao_serial3_set_speed
-
-#define HAS_EEPROM 0
-#define USE_INTERNAL_FLASH 0
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_STORAGE_CONFIG 0
+#define USE_EEPROM_CONFIG 1
#define HAS_USB 1
#define HAS_BEEP 0
#define HAS_RADIO 1
#define HAS_TELEMETRY 0
+#define HAS_RSSI 1
#define HAS_SPI_1 0
#define SPI_1_PA5_PA6_PA7 0 /* Barometer */
#define SPI_1_PE13_PE14_PE15 0 /* Accelerometer */
#define HAS_SPI_2 1
-#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */
+#define SPI_2_PB13_PB14_PB15 1 /* Radio */
#define SPI_2_PD1_PD3_PD4 0
#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
#define SPI_2_MISO_PIN 14
#define SPI_2_MOSI_PIN 15
-#define HAS_I2C_1 0
-#define I2C_1_PB8_PB9 1
-
-#define HAS_I2C_2 0
-#define I2C_2_PB10_PB11 1
-
#define PACKET_HAS_SLAVE 0
#define PACKET_HAS_MASTER 1
#define LOW_LEVEL_DEBUG 0
-#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
-#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
-#define LED_PORT_0 (&stm_gpioa)
-#define LED_PORT_0_MASK (0xff)
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT_0 (&stm_gpioc)
+#define LED_PORT_0_MASK (0xffff)
#define LED_PORT_0_SHIFT 0
-#define LED_PORT_1_MASK (0xff00)
-#define LED_PORT_1_SHIFT 0
-#define LED_PORT_1 (&stm_gpiob)
-#define LED_PIN_RED 1
-#define LED_PIN_GREEN 12
+#define LED_PIN_RED 14
+#define LED_PIN_GREEN 15
#define AO_LED_RED (1 << LED_PIN_RED)
#define AO_LED_GREEN (1 << LED_PIN_GREEN)
#define AO_FEC_DEBUG 0
#define AO_CC1120_SPI_CS_PORT (&stm_gpioa)
-#define AO_CC1120_SPI_CS_PIN 0
+#define AO_CC1120_SPI_CS_PIN 2
#define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15
#define AO_CC1120_SPI stm_spi2
-#define AO_CC1120_INT_PORT (&stm_gpioc)
-#define AO_CC1120_INT_PIN 13
+#define AO_CC1120_INT_PORT (&stm_gpioa)
+#define AO_CC1120_INT_PIN 3
-#define AO_CC1120_MCU_WAKEUP_PORT (&stm_gpioc)
-#define AO_CC1120_MCU_WAKEUP_PIN (0)
+#define AO_CC1120_MCU_WAKEUP_PORT (&stm_gpioa)
+#define AO_CC1120_MCU_WAKEUP_PIN (4)
#define AO_CC1120_INT_GPIO 2
#define AO_CC1120_INT_GPIO_IOCFG CC1120_IOCFG2
--- /dev/null
+ao_product.h
+microkite-*
--- /dev/null
+#
+# Tiny AltOS build
+#
+#
+vpath % ../attiny:../drivers:../kernel:../product:..
+vpath ao-make-product.5c ../util
+vpath make-altitude-pa ../util
+
+include ../avr/Makefile.defs
+
+PROGNAME=microkite-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SCRIPT=microkite-load
+
+PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
+PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX)
+PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT)
+
+MCU=attiny85
+DUDECPUTYPE=t85
+#PROGRAMMER=stk500v2 -P usb
+LOADSLOW=-i 32 -B 32
+LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
+
+#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
+
+ALTOS_SRC = \
+ ao_micropeak.c \
+ ao_spi_attiny.c \
+ ao_led.c \
+ ao_clock.c \
+ ao_ms5607.c \
+ ao_exti.c \
+ ao_convert_pa.c \
+ ao_report_micro.c \
+ ao_notask.c \
+ ao_eeprom_tiny.c \
+ ao_panic.c \
+ ao_log_micro.c \
+ ao_async.c \
+ ao_microflight.c \
+ ao_microkalman.c
+
+INC=\
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_exti.h \
+ ao_ms5607.h \
+ ao_log_micro.h \
+ ao_micropeak.h \
+ altitude-pa.h
+
+IDPRODUCT=0
+PRODUCT=MicroKite-v0.1
+PRODUCT_DEF=-DMICROPEAK
+CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
+CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
+
+NICKLE=nickle
+
+SRC=$(ALTOS_SRC)
+OBJ=$(SRC:.c=.o)
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf " $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: $(PROG) $(HEX) microkite-load
+
+CHECK=sh ../util/check-avr-mem
+
+$(PROG): Makefile $(OBJ)
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
+ $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
+
+$(HEX): $(PROG)
+ avr-size $(PROG)
+ $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
+
+
+load: $(HEX)
+ $(LOADCMD) $(LOADARG)$(HEX)
+
+load-slow: $(HEX)
+ $(LOADCMD) $(LOADSLOW) $(LOADARG)$(HEX)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+ao_product.o: ao_product.c ao_product.h
+
+%.o : %.c $(INC)
+ $(call quiet,CC) -c $(CFLAGS) $<
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROG) $(HEX) $(SCRIPT)
+ rm -f ao_product.h
+
+publish: $(PUBLISH_HEX) $(PUBLISH_SCRIPT)
+
+$(PUBLISH_HEX): $(HEX)
+ cp -a $(HEX) $@
+
+$(PUBLISH_SCRIPT): $(SCRIPT)
+ cp -a $(SCRIPT) $@
+
+load-product:
+ ./$(SCRIPT) fast
+
+load-product-slow:
+ ./$(SCRIPT) slow
+
+../altitude-pa.h: make-altitude-pa
+ nickle $< > $@
+
+$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version
+ sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1)
+ chmod +x $@
+
+install:
+
+uninstall:
+
+$(OBJ): ao_product.h $(INC)
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+#include <avr/pgmspace.h>
+
+#define AO_LED_ORANGE (1<<4)
+#define AO_LED_SERIAL 4
+#define AO_LED_PANIC AO_LED_ORANGE
+#define AO_LED_REPORT AO_LED_ORANGE
+#define LEDS_AVAILABLE (AO_LED_ORANGE)
+#define USE_SERIAL_1_STDIN 0
+#define HAS_USB 0
+#define PACKET_HAS_SLAVE 0
+#define HAS_SERIAL_1 0
+#define HAS_TASK 0
+#define HAS_MS5607 1
+#define HAS_MS5611 0
+#define HAS_EEPROM 0
+#define HAS_BEEP 0
+#define AVR_CLOCK 250000UL
+
+/* SPI */
+#define SPI_PORT PORTB
+#define SPI_PIN PINB
+#define SPI_DIR DDRB
+#define AO_MS5607_CS_PORT PORTB
+#define AO_MS5607_CS_PIN 3
+
+/* MS5607 */
+#define AO_MS5607_SPI_INDEX 0
+#define AO_MS5607_MISO_PORT PORTB
+#define AO_MS5607_MISO_PIN 0
+#define AO_MS5607_BARO_OVERSAMPLE 4096
+#define AO_MS5607_TEMP_OVERSAMPLE 1024
+
+/* I2C */
+#define I2C_PORT PORTB
+#define I2C_PIN PINB
+#define I2C_DIR DDRB
+#define I2C_PIN_SCL PINB2
+#define I2C_PIN_SDA PINB0
+
+#define AO_CONST_ATTRIB PROGMEM
+typedef int32_t alt_t;
+#define FETCH_ALT(o) ((alt_t) pgm_read_dword(&altitude_table[o]))
+
+#define AO_ALT_VALUE(x) ((x) * (alt_t) 10)
+
+#define BOOST_DETECT 0 /* none */
+#define LOG_INTERVAL 200 /* 19.2 seconds */
+#define BOOST_DELAY 0
+
+#define AO_LOG_ID AO_LOG_ID_MICROKITE
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+#!/bin/sh
+dir=`dirname $0`
+
+HEX="$dir"/"%HEX%"
+LOADCMD="%LOADCMD%"
+LOADARG="%LOADARG%"
+LOADSLOW="%LOADSLOW%"
+LOADFAST=""
+
+case "$1" in
+fast)
+ LOADSPEED="$LOADFAST"
+ ;;
+*)
+ LOADSPEED="$LOADSLOW"
+ ;;
+esac
+
+echo ${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX}
+${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX}
include ../avr/Makefile.defs
+PROGNAME=micropeak-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SCRIPT=micropeak-load
+
PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
-PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex
+PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX)
+PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT)
MCU=attiny85
DUDECPUTYPE=t85
NICKLE=nickle
-PROG=micropeak-v0.1
-
SRC=$(ALTOS_SRC)
OBJ=$(SRC:.c=.o)
# Otherwise, print the full command line.
quiet ?= $($1)
-all: $(PROG) $(PROG).hex
+all: $(PROG) $(HEX) micropeak-load
CHECK=sh ../util/check-avr-mem
$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
$(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
-$(PROG).hex: $(PROG)
+$(HEX): $(PROG)
avr-size $(PROG)
$(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
-load: $(PROG).hex
- $(LOADCMD) $(LOADARG)$(PROG).hex
+load: $(HEX)
+ $(LOADCMD) $(LOADARG)$(HEX)
-load-slow: $(PROG).hex
- $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex
+load-slow: $(HEX)
+ $(LOADCMD) $(LOADSLOW) $(LOADARG)$(HEX)
ao_product.h: ao-make-product.5c ../Version
$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
distclean: clean
clean:
- rm -f *.o $(PROG) $(PROG).hex
+ rm -f *.o $(PROG) $(HEX) $(SCRIPT)
rm -f ao_product.h
+publish: $(PUBLISH_HEX) $(PUBLISH_SCRIPT)
-publish: $(PROG).hex
- cp -a $(PROG).hex $(PUBLISH_FILE)
+$(PUBLISH_HEX): $(HEX)
+ cp -a $(HEX) $@
+
+$(PUBLISH_SCRIPT): $(SCRIPT)
+ cp -a $(SCRIPT) $@
load-product:
- $(LOADCMD) $(LOADARG)$(PUBLISH_FILE)
+ ./$(SCRIPT) fast
load-product-slow:
- $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE)
+ ./$(SCRIPT) slow
../altitude-pa.h: make-altitude-pa
nickle $< > $@
+$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version
+ sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1)
+ chmod +x $@
+
install:
uninstall:
--- /dev/null
+#!/bin/sh
+dir=`dirname $0`
+
+HEX="$dir"/"%HEX%"
+LOADCMD="%LOADCMD%"
+LOADARG="%LOADARG%"
+LOADSLOW="%LOADSLOW%"
+LOADFAST=""
+
+case "$1" in
+fast)
+ LOADSPEED="$LOADFAST"
+ ;;
+*)
+ LOADSPEED="$LOADSLOW"
+ ;;
+esac
+
+echo ${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX}
+${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX}
all: $(PROG)
$(PROG): $(REL) Makefile
- $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)
$(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@
ao_product.h: ao-make-product.5c ../Version
all: $(PROG)
$(PROG): $(REL) Makefile
- $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)
$(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@
ao_product.h: ao-make-product.5c ../Version
altitude.h \
ao_kalman.h \
ao_product.h \
+ ao_telemetry.h \
$(TM_INC)
CORE_SRC = \
all: $(PROG)
$(PROG): $(REL) Makefile
- $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)
$(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@
ao_product.h: ao-make-product.5c ../Version
ao_report_altitude();
ao_pips();
ao_log_micro_dump();
-
+#if BOOST_DELAY
ao_delay(BOOST_DELAY);
+#endif
ao_microflight();
#define BOOST_DETECT 360 /* 30m at sea level, 36m at 2000m */
#endif
+#ifndef LOG_INTERVAL
+#define LOG_INTERVAL 2 /* 192 ms */
+#endif
+
+#define AO_LOG_ID_MICROPEAK 0
+#define AO_LOG_ID_MICROKITE 1
+
+#ifndef AO_LOG_ID
+#define AO_LOG_ID AO_LOG_ID_MICROPEAK
+#endif
+
/* Wait after power on before doing anything to give the user time to assemble the rocket */
+#ifndef BOOST_DELAY
#define BOOST_DELAY AO_SEC_TO_TICKS(60)
+#endif
/* Pressure change (in Pa) to detect landing */
#define LAND_DETECT 24 /* 2m at sea level, 2.4m at 2000m */
#define AO_SPI_INDEX(id) ((id) & AO_SPI_INDEX_MASK)
#define AO_SPI_CONFIG(id) ((id) & AO_SPI_CONFIG_MASK)
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id);
+
void
ao_spi_get(uint8_t spi_index, uint32_t speed);
void
ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index);
+
void
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
ao_spi_set_cs(reg,mask); \
} while (0)
+static inline uint8_t
+ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id)
+{
+ if (!ao_spi_try_get(bus, speed, task_id))
+ return 0;
+ ao_spi_set_cs(reg, mask);
+ return 1;
+}
+
#define ao_spi_put_mask(reg,mask,bus) do { \
ao_spi_clr_cs(reg,mask); \
ao_spi_put(bus); \
#define ARM_PUSH32(stack, val) (*(--(stack)) = (val))
+typedef uint32_t ao_arch_irq_t;
+
static inline uint32_t
ao_arch_irqsave(void) {
uint32_t primask;
ao_arch_block_interrupts(); \
} while (0)
-#define ao_arch_critical(b) do { \
- ao_arch_block_interrupts(); \
- do { b } while (0); \
- ao_arch_release_interrupts(); \
+#define ao_arch_critical(b) do { \
+ uint32_t __mask = ao_arch_irqsave(); \
+ do { b } while (0); \
+ ao_arch_irqrestore(__mask); \
} while (0)
#endif /* _AO_ARCH_FUNCS_H_ */
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 = ((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 (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)
{
}
}
-void
-ao_spi_get(uint8_t spi_index, uint32_t speed)
+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;
-
- ao_mutex_get(&ao_spi_mutex[id]);
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_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)
{
#define BT_LINK_PIN P1_7
#define HAS_MONITOR 1
#define LEGACY_MONITOR 0
+#define HAS_TELEMETRY 0
+#define AO_RADIO_REG_TEST 1
#define HAS_ADC 1
#define AO_PAD_ADC_BATT 0
CORE_SRC = \
ao_cmd.c \
ao_config.c \
- ao_convert.c \
ao_mutex.c \
ao_panic.c \
ao_stdio.c \
#ifndef _AO_PINS_H_
#define _AO_PINS_H_
-#define HAS_RADIO 1
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 0
#define HAS_FLIGHT 0
#define HAS_USB 1
CORE_SRC = \
ao_cmd.c \
ao_config.c \
- ao_convert.c \
ao_mutex.c \
ao_panic.c \
ao_stdio.c \
#ifndef _AO_PINS_H_
#define _AO_PINS_H_
-#define HAS_RADIO 1
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
#define HAS_FLIGHT 0
#define HAS_USB 1
#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1) | (1 << AO_PAD_PIN_2) | (1 << AO_PAD_PIN_3))
#define AO_PAD_ALL_CHANNELS ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
+/* Alarm 2 */
#define AO_SIREN_PORT P2
#define AO_SIREN_DIR P2DIR
#define AO_SIREN_PIN 3
#define AO_SIREN P2_3
+/* Alarm 1 */
#define AO_STROBE_PORT P2
#define AO_STROBE_DIR P2DIR
#define AO_STROBE_PIN 4
#define HAS_GPS 1
#define HAS_FLIGHT 0
#define HAS_LOG 1
+#define FLIGHT_LOG_APPEND 1
#define HAS_TRACKER 1
#define AO_CONFIG_DEFAULT_APRS_INTERVAL 0
#define AO_CONFIG_DEFAULT_RADIO_POWER 0xc0
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX 496 * 1024
/*
* GPS
for (box = 0; box < AO_PAD_MAX_BOXES; box++) {
if ((box % 10) == 0)
ao_lco_set_box(box);
- for (try = 0; try < 5; try++) {
+ for (try = 0; try < 3; try++) {
tick_offset = 0;
r = ao_lco_query(box, &ao_pad_query, &tick_offset);
PRINTD("box %d result %d\n", box, r);
#define HAS_USB 1
#define HAS_BEEP 1
#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
#define HAS_TELEMETRY 0
#define HAS_AES 1
ao_mpu.h \
stm32l.h \
math.h \
+ ao_ms5607_convert.c \
Makefile
#
ao_int64.h \
ao_sample.h \
ao_exti.h \
- ao_task.h
+ ao_task.h \
+ altitude-pa-small.h
CORE_SRC = \
ao_cmd.c \
#define HAS_FLIGHT 1
#define HAS_USB 1
+#define AO_VALUE_32 0
#define HAS_USB_PULLUP 1
#define AO_USB_PULLUP_PORT P1
#define AO_USB_PULLUP_PIN 0
#define AO_USB_PULLUP P1_0
+#define AO_SMALL_ALTITUDE_TABLE 1
+
#define USB_FORCE_FLIGHT_IDLE 1
#define HAS_BEEP 1
-#define HAS_BEEP_CONFIG 0
+#define HAS_BEEP_CONFIG 1
#define HAS_BATTERY_REPORT 1
#define HAS_GPS 0
#define HAS_SERIAL_1 0
#define USE_INTERNAL_FLASH 0
#define HAS_DBG 0
#define PACKET_HAS_SLAVE 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 1
#define AO_LED_RED 2
#define LEDS_AVAILABLE AO_LED_RED
--- /dev/null
+#
+# TeleRepeat build file
+#
+
+TELEREPEAT_VER=1.0
+TELEREPEAT_DEF=1_0
+
+vpath %.c ..:../kernel:../cc1111:../drivers:../product
+vpath %.h ..:../kernel:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ cc1111.h \
+ ao_product.h
+
+CORE_SRC = \
+ ao_cmd.c \
+ ao_config.c \
+ ao_monitor.c \
+ ao_mutex.c \
+ ao_panic.c \
+ ao_state.c \
+ ao_stdio.c \
+ ao_task.c \
+ ao_forward.c \
+ ao_storage.c \
+ ao_freq.c
+
+CC1111_SRC = \
+ ao_dbg.c \
+ ao_adc.c \
+ ao_dma.c \
+ ao_led.c \
+ ao_packet.c \
+ ao_intflash.c \
+ ao_packet_master.c \
+ ao_radio.c \
+ ao_romconfig.c \
+ ao_serial.c \
+ ao_string.c \
+ ao_timer.c \
+ ao_usb.c \
+ _bp.c
+
+DRIVER_SRC = \
+ ao_btm.c
+
+PRODUCT_SRC = \
+ ao_telerepeat.c
+
+SRC = \
+ $(CORE_SRC) \
+ $(CC1111_SRC) \
+ $(DRIVER_SRC) \
+ $(PRODUCT_SRC)
+
+PROGNAME = telerepeat-v$(TELEREPEAT_VER)
+PROG = $(PROGNAME)-$(VERSION).ihx
+PRODUCT=TeleRepeat-v$(TELEREPEAT_VER)
+PRODUCT_DEF=-DTELEREPEAT_V_$(TELEREPEAT_DEF)
+IDPRODUCT=0x000e
+CODESIZE=0x7800
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf " $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: $(PROG)
+
+$(PROG): $(REL) Makefile
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)
+ $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean: clean-cc1111
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * 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_FORWARD 1
+#define HAS_FLIGHT 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_SERIAL_1 1
+#define HAS_SERIAL_1_ALT_1 1
+#define HAS_SERIAL_1_ALT_2 0
+#define HAS_SERIAL_1_HW_FLOW 1
+#define USE_SERIAL_1_STDIN 1
+#define DELAY_SERIAL_1_STDIN 1
+#define HAS_DBG 1
+#define HAS_EEPROM 1
+#define HAS_LOG 0
+#define USE_INTERNAL_FLASH 1
+#define HAS_BTM 1
+#define DBG_ON_P1 1
+#define DBG_ON_P0 0
+#define PACKET_HAS_MASTER 1
+#define PACKET_HAS_SLAVE 0
+#define AO_LED_RED 1
+#define AO_LED_BLUE 2
+#define LEDS_AVAILABLE (AO_LED_RED|AO_LED_BLUE)
+#define AO_MONITOR_LED AO_LED_RED
+#define AO_BT_LED AO_LED_BLUE
+#define BT_LINK_ON_P2 0
+#define BT_LINK_ON_P1 1
+#define BT_LINK_PIN_INDEX 7
+#define BT_LINK_PIN P1_7
+#define HAS_MONITOR 1
+#define HAS_MONITOR_PUT 1
+#define LEGACY_MONITOR 0
+#define HAS_TELEMETRY 0
+#define AO_RADIO_REG_TEST 1
+
+#define HAS_ADC 1
+#define AO_PAD_ADC_BATT 0
+#define AO_ADC_PINS (1 << AO_PAD_ADC_BATT)
+
+struct ao_adc {
+ int16_t batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf ("tick: %5u batt %5d\n", \
+ (p)->tick, \
+ (p)->adc.batt)
+
+#define FETCH_ADC() do { \
+ a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.batt); \
+ a[0] = ADCL; \
+ a[1] = ADCH; \
+ } while (0)
+
+#if DBG_ON_P1
+
+ #define DBG_CLOCK (1 << 4) /* mi0 */
+ #define DBG_DATA (1 << 5) /* mo0 */
+ #define DBG_RESET_N (1 << 3) /* c0 */
+
+ #define DBG_CLOCK_PIN (P1_4)
+ #define DBG_DATA_PIN (P1_5)
+ #define DBG_RESET_N_PIN (P1_3)
+
+ #define DBG_PORT_NUM 1
+ #define DBG_PORT P1
+ #define DBG_PORT_SEL P1SEL
+ #define DBG_PORT_INP P1INP
+ #define DBG_PORT_DIR P1DIR
+
+#endif /* DBG_ON_P1 */
+
+#if DBG_ON_P0
+
+ #define DBG_CLOCK (1 << 3)
+ #define DBG_DATA (1 << 4)
+ #define DBG_RESET_N (1 << 5)
+
+ #define DBG_CLOCK_PIN (P0_3)
+ #define DBG_DATA_PIN (P0_4)
+ #define DBG_RESET_N_PIN (P0_5)
+
+ #define DBG_PORT_NUM 0
+ #define DBG_PORT P0
+ #define DBG_PORT_SEL P0SEL
+ #define DBG_PORT_INP P0INP
+ #define DBG_PORT_DIR P0DIR
+
+#endif /* DBG_ON_P0 */
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * 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_forward.h"
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ /* Turn on the LED until the system is stable */
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_RED);
+
+ ao_task_init();
+
+ ao_timer_init();
+ ao_cmd_init();
+ ao_usb_init();
+ ao_monitor_init();
+ ao_radio_init();
+ ao_packet_master_init();
+ ao_adc_init();
+ ao_btm_init();
+ ao_monitor_forward_init();
+ ao_storage_init();
+#if HAS_DBG
+ ao_dbg_init();
+#endif
+ ao_config_init();
+ ao_start_scheduler();
+}
#define HAS_RSSI 0
#define HAS_AES 0
#define HAS_RADIO 1
+ #define HAS_TELEMETRY 0
#endif
#if DBG_ON_P1
#define HAS_P2_ISR 1
#define BATTERY_PIN 5
-
+ #define HAS_TELEMETRY 0
+
+ #define AO_VALUE_32 0
#endif
#if DBG_ON_P1
vpath % ..:../kernel:../drivers:../util:../micropeak:../aes:../product
PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \
+ ao_flight_test_metrum \
ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \
ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \
ao_ms5607_convert_test ao_quaternion_test
ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
cc -DTELEMEGA=1 $(CFLAGS) -o $@ $< -lm
+ao_flight_test_metrum: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)
+ cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $< -lm
+
ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h
cc $(CFLAGS) -o $@ $<
#include <stdint.h>
#include <stdarg.h>
+#define HAS_GPS 1
+
#include <ao_telemetry.h>
#define AO_GPS_NUM_SAT_MASK (0xf << 0)
#endif
}
-#include <math.h>
-
-int
-ao_aprs_encode_altitude_expensive(int meters)
-{
- double feet = meters / 0.3048;
-
- double encode = log(feet) / log(1.002);
- return floor(encode + 0.5);
-}
-
// This is where we go after reset.
int main(int argc, char **argv)
{
- int e, x;
- int a;
-
- for (a = 1; a < 100000; a++) {
- e = ao_aprs_encode_altitude(a);
- x = ao_aprs_encode_altitude_expensive(a);
-
- if (e != x) {
- double back_feet, back_meters;
- back_feet = pow(1.002, e);
- back_meters = back_feet * 0.3048;
- fprintf (stderr, "APRS altitude encoding failure: altitude %d actual %d expected %d actual meters %f\n",
- a, e, x, back_meters);
- }
- }
-
audio_gap(1);
ao_gps_data.latitude = (45.0 + 28.25 / 60.0) * 10000000;
ao_gps_data.longitude = (-(122 + 44.2649 / 60.0)) * 10000000;
- ao_gps_data.altitude = 84;
+ AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_data, 84);
ao_gps_data.flags = (AO_GPS_VALID|AO_GPS_RUNNING);
/* Transmit one packet */
#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1))
#define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1))
+#if 0
#define AO_M_TO_HEIGHT(m) ((int16_t) (m))
#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16))
#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16))
+#endif
#define AO_GPS_NEW_DATA 1
#define AO_GPS_NEW_TRACKING 2
int ao_gps_new;
+#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2)
+#define TELEMETRUM_V1 1
+#endif
+
#if TELEMEGA
#define AO_ADC_NUM_SENSE 6
#define HAS_MS5607 1
#define HAS_MMA655X 1
#define HAS_HMC5883 1
#define HAS_BEEP 1
+#define AO_CONFIG_MAX_SIZE 1024
struct ao_adc {
int16_t sense[AO_ADC_NUM_SENSE];
int16_t v_pbatt;
int16_t temp;
};
-#else
+#endif
+
+#if TELEMETRUM_V2
+#define AO_ADC_NUM_SENSE 2
+#define HAS_MS5607 1
+#define HAS_MMA655X 1
+#define HAS_BEEP 1
+#define AO_CONFIG_MAX_SIZE 1024
+
+struct ao_adc {
+ int16_t sense_a;
+ int16_t sense_m;
+ int16_t v_batt;
+ int16_t temp;
+};
+#endif
+
+
+#if TELEMETRUM_V1
/*
* One set of samples read from the A/D converter
*/
#include <ao_data.h>
#include <ao_log.h>
#include <ao_telemetry.h>
+#include <ao_sample.h>
#if TELEMEGA
int ao_gps_count;
ao_gps_static.latitude / 1e7,
ao_gps_static.longitude / 1e7,
&dist, &bearing);
- height = ao_gps_static.altitude - ao_gps_prev.altitude;
+ height = AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_static) - AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_prev);
angle = atan2(dist, height);
return angle * 180/M_PI;
#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
#define from_fix(x) ((x) >> 16)
-/*
- * Above this height, the baro sensor doesn't work
- */
-#define AO_BARO_SATURATE 13000
-#define AO_MIN_BARO_VALUE ao_altitude_to_pres(AO_BARO_SATURATE)
-
-/*
- * Above this speed, baro measurements are unreliable
- */
-#define AO_MAX_BARO_SPEED 200
-
#define ACCEL_NOSE_UP (ao_accel_2g >> 2)
extern enum ao_flight_state ao_flight_state;
int tick_offset;
-static int32_t ao_k_height;
+static ao_k_t ao_k_height;
int16_t
ao_time(void)
#define ao_xmemcmp(d,s,c) memcmp(d,s,c)
#define AO_NEED_ALTITUDE_TO_PRES 1
-#if TELEMEGA
+#if TELEMEGA || TELEMETRUM_V2
#include "ao_convert_pa.c"
#include <ao_ms5607.h>
struct ao_ms5607_prom ao_ms5607_prom;
#else
double accel = 0.0;
#endif
-#if TELEMEGA
+#if TELEMEGA || TELEMETRUM_V2
double height;
ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked);
mag_azel.el,
mag_azel.az);
#endif
+#if 0
printf ("%7.2f state %-8.8s height %8.4f tilt %4d rot %4d dist %12.2f gps_tilt %4d gps_sats %2d\n",
time,
ao_state_names[ao_flight_state],
(int) floor (ao_gps_angle() + 0.5),
(ao_gps_static.flags & 0xf) * 10);
+#endif
#if 0
printf ("\t\tstate %-8.8s ground az: %4d el %4d mag az %4d el %4d rot az %4d el %4d el_diff %4d az_diff %4d angle %4d tilt %4d ground %8.5f %8.5f %8.5f cur %8.5f %8.5f %8.5f rot %8.5f %8.5f %8.5f\n",
ao_state_names[ao_flight_state],
#endif
#endif
-#if 0
+#if 1
printf("%7.2f height %8.2f accel %8.3f "
-#if TELEMEGA
+#if TELEMEGA && 0
"angle %5d "
"accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d "
#endif
time,
height,
accel,
-#if TELEMEGA
+#if TELEMEGA && 0
ao_sample_orient,
ao_mpu6000_accel(ao_data_static.mpu6000.accel_x),
{
#if TELEMEGA
ao_data_static.mpu6000 = ao_ground_mpu6000;
-#else
+#endif
+#if TELEMETRUM_V1
ao_data_static.adc.accel = ao_flight_ground_accel;
#endif
ao_insert();
ao_gps_static.tick = tick;
ao_gps_static.latitude = int32(bytes, 0);
ao_gps_static.longitude = int32(bytes, 4);
- ao_gps_static.altitude = int32(bytes, 8);
+ {
+ int32_t altitude = int32(bytes, 8);
+ AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude);
+ }
ao_gps_static.flags = bytes[13];
if (!ao_gps_count)
ao_gps_first = ao_gps_static;
pyro->flags |= ao_pyro_values[j].flag;
if (ao_pyro_values[j].offset != NO_VALUE && i + 1 < nword) {
int16_t val = strtoul(words[++i], NULL, 10);
+ printf("pyro %d condition %s value %d\n", p, words[i-1], val);
*((int16_t *) ((char *) pyro + ao_pyro_values[j].offset)) = val;
}
}
}
-#else
+#endif
+#if TELEMETRUM_V2
+ if (log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && strlen(words[0]) == 1) {
+ int i;
+ struct ao_ms5607_value value;
+
+ type = words[0][0];
+ tick = strtoul(words[1], NULL, 16);
+// printf ("%c %04x", type, tick);
+ for (i = 2; i < nword; i++) {
+ bytes[i - 2] = strtoul(words[i], NULL, 16);
+// printf(" %02x", bytes[i-2]);
+ }
+// printf ("\n");
+ switch (type) {
+ case 'F':
+ ao_flight_ground_accel = int16(bytes, 2);
+ ao_flight_started = 1;
+ ao_ground_pres = int32(bytes, 4);
+ ao_ground_height = ao_pa_to_altitude(ao_ground_pres);
+ break;
+ case 'A':
+ ao_data_static.tick = tick;
+ ao_data_static.ms5607_raw.pres = int32(bytes, 0);
+ ao_data_static.ms5607_raw.temp = int32(bytes, 4);
+ ao_ms5607_convert(&ao_data_static.ms5607_raw, &value);
+ ao_data_static.mma655x = int16(bytes, 8);
+ ao_records_read++;
+ ao_insert();
+ return;
+ }
+ continue;
+ } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) {
+ if (strcmp(words[1], "reserved:") == 0)
+ ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "sens:") == 0)
+ ao_ms5607_prom.sens = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "off:") == 0)
+ ao_ms5607_prom.off = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "tcs:") == 0)
+ ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "tco:") == 0)
+ ao_ms5607_prom.tco = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "tref:") == 0)
+ ao_ms5607_prom.tref = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "tempsens:") == 0)
+ ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10);
+ else if (strcmp(words[1], "crc:") == 0)
+ ao_ms5607_prom.crc = strtoul(words[2], NULL, 10);
+ continue;
+ }
+#endif
+#if TELEMETRUM_V1
if (nword == 4 && log_format != AO_LOG_FORMAT_TELEMEGA) {
type = words[0][0];
tick = strtoul(words[1], NULL, 16);
if (type != 'F' && !ao_flight_started)
continue;
-#if TELEMEGA
+#if TELEMEGA || TELEMETRUM_V2
(void) a;
(void) b;
#else
ao_data_static.tick = tick;
ao_data_static.adc.accel = a;
ao_data_static.adc.pres_real = b;
- if (b < AO_MIN_BARO_VALUE)
- b = AO_MIN_BARO_VALUE;
ao_data_static.adc.pres = b;
ao_records_read++;
ao_insert();
uint16_t v_error; /* m */
};
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l) ((l)->altitude)
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) ((l)->altitude = (a))
+
#define SIRF_SAT_STATE_ACQUIRED (1 << 0)
#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1)
#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2)
if (wchan != &ao_gps_new)
return;
-
+
if (ao_gps_new & AO_GPS_NEW_DATA) {
ao_gps_print(&ao_gps_data);
putchar('\n');
*/
#define AO_GPS_TEST
+#define HAS_GPS 1
#include "ao_host.h"
#include <termios.h>
#include <errno.h>
uint16_t v_error; /* m */
};
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l) ((l)->altitude)
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) ((l)->altitude = (a))
+
#define SIRF_SAT_STATE_ACQUIRED (1 << 0)
#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1)
#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2)
*/
#define AO_GPS_TEST
+#define HAS_GPS 1
#include "ao_host.h"
#include <termios.h>
#include <errno.h>
uint8_t flags;
int32_t latitude; /* degrees * 10⁷ */
int32_t longitude; /* degrees * 10⁷ */
- int16_t altitude; /* m */
+ int16_t altitude_low; /* m */
uint16_t ground_speed; /* cm/s */
uint8_t course; /* degrees / 2 */
uint8_t pdop; /* * 5 */
int16_t climb_rate; /* cm/s */
uint16_t h_error; /* m */
uint16_t v_error; /* m */
+ int16_t altitude_high; /* m */
};
+typedef int32_t gps_alt_t;
+#define AO_TELEMETRY_LOCATION_ALTITUDE(l) (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low))
+#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->altitude_high = (a) >> 16), \
+ ((l)->altitude_low = (a)))
+
#define UBLOX_SAT_STATE_ACQUIRED (1 << 0)
#define UBLOX_SAT_STATE_CARRIER_PHASE_VALID (1 << 1)
#define UBLOX_SAT_BIT_SYNC_COMPLETE (1 << 2)
#define AO_FLIGHT_TEST
typedef int32_t alt_t;
+typedef int32_t pres_t;
#define AO_MS_TO_TICKS(ms) ((ms) / 10)
"$1" using 1:9 with lines axes x1y1 title "height",\
"$1" using 1:11 with lines axes x1y2 title "speed",\
"$1" using 1:13 with lines axes x1y2 title "accel",\
-"$1" using 1:15 with lines axes x1y1 title "drogue",\
-"$1" using 1:17 with lines axes x1y1 title "main",\
-"$1" using 1:19 with lines axes x1y1 title "error"
+"$1" using 1:17 with lines axes x1y1 title "drogue",\
+"$1" using 1:19 with lines axes x1y1 title "main",\
+"$1" using 1:21 with lines axes x1y1 title "error"
EOF
return (line_t) { m = m, b = b };
}
-real min_Pa = 0;
-real max_Pa = 120000;
+void print_table (int pa_sample_shift, int pa_part_shift)
+{
+ real min_Pa = 0;
+ real max_Pa = 120000;
-/* Target is an array of < 1000 entries */
-int pa_sample_shift = 2;
-int pa_part_shift = 6;
-int pa_part_mask = (1 << pa_part_shift) - 1;
+ int pa_part_mask = (1 << pa_part_shift) - 1;
-int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift)));
+ int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift)));
-int num_samples = num_part << pa_part_shift;
+ int num_samples = num_part << pa_part_shift;
-real sample_to_Pa(int sample) = sample << pa_sample_shift;
+ real sample_to_Pa(int sample) = sample << pa_sample_shift;
-real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample));
+ real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample));
-int part_to_sample(int part) = part << pa_part_shift;
+ int part_to_sample(int part) = part << pa_part_shift;
-int sample_to_part(int sample) = sample >> pa_part_shift;
+ int sample_to_part(int sample) = sample >> pa_part_shift;
-bool is_part(int sample) = (sample & pa_part_mask) == 0;
+ bool is_part(int sample) = (sample & pa_part_mask) == 0;
-real[num_samples] alt = { [n] = sample_to_altitude(n) };
+ real[num_samples] alt = { [n] = sample_to_altitude(n) };
-int seg_len = 1 << pa_part_shift;
+ int seg_len = 1 << pa_part_shift;
-line_t [num_part] fit = {
- [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1)
-};
-
-real[num_samples/seg_len + 1] alt_part;
-real[dim(alt_part)] alt_error = {0...};
-
-alt_part[0] = fit[0].b;
-alt_part[dim(fit)] = fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b;
+ line_t [num_part] fit = {
+ [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1)
+ };
-for (int i = 0; i < dim(fit) - 1; i++) {
- real here, there;
- here = fit[i].m * (i+1) * seg_len + fit[i].b;
- there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b;
-# printf ("at %d mis-fit %8.2f\n", i, there - here);
- alt_part[i+1] = (here + there) / 2;
-}
+ real[num_samples/seg_len + 1] alt_part;
+ real[dim(alt_part)] alt_error = {0...};
-real round(real x) = floor(x + 0.5);
+ alt_part[0] = fit[0].b;
+ alt_part[dim(fit)] = fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b;
-real sample_to_fit_altitude(int sample) {
- int sub = sample // seg_len;
- int off = sample % seg_len;
- line_t l = fit[sub];
- real r_v;
- real i_v;
+ for (int i = 0; i < dim(fit) - 1; i++) {
+ real here, there;
+ here = fit[i].m * (i+1) * seg_len + fit[i].b;
+ there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b;
+# printf ("at %d mis-fit %8.2f\n", i, there - here);
+ alt_part[i+1] = (here + there) / 2;
+ }
- r_v = sample * l.m + l.b;
- i_v = (round(alt_part[sub]*10) * (seg_len - off) + round(alt_part[sub+1]*10) * off) / seg_len;
- return i_v/10;
-}
+ real round(real x) = floor(x + 0.5);
-real max_error = 0;
-int max_error_sample = 0;
-real total_error = 0;
+ real sample_to_fit_altitude(int sample) {
+ int sub = sample // seg_len;
+ int off = sample % seg_len;
+ line_t l = fit[sub];
+ real r_v;
+ real i_v;
-for (int sample = 0; sample < num_samples; sample++) {
- real Pa = sample_to_Pa(sample);
- real meters = alt[sample];
+ r_v = sample * l.m + l.b;
+ i_v = (round(alt_part[sub]*10) * (seg_len - off) + round(alt_part[sub+1]*10) * off) / seg_len;
+ return i_v/10;
+ }
- real meters_approx = sample_to_fit_altitude(sample);
- real error = abs(meters - meters_approx);
+ real max_error = 0;
+ int max_error_sample = 0;
+ real total_error = 0;
+
+ for (int sample = 0; sample < num_samples; sample++) {
+ real Pa = sample_to_Pa(sample);
+ real meters = alt[sample];
+
+ real meters_approx = sample_to_fit_altitude(sample);
+ real error = abs(meters - meters_approx);
+
+ int part = sample_to_part(sample);
+
+ if (error > alt_error[part])
+ alt_error[part] = error;
+
+ total_error += error;
+ if (error > max_error) {
+ max_error = error;
+ max_error_sample = sample;
+ }
+ if (false) {
+ printf (" %8.1f %8.2f %8.2f %8.2f %s\n",
+ Pa,
+ meters,
+ meters_approx,
+ meters - meters_approx,
+ is_part(sample) ? "*" : "");
+ }
+ }
- int part = sample_to_part(sample);
+ printf ("/*max error %f at %7.3f kPa. Average error %f*/\n",
+ max_error, sample_to_Pa(max_error_sample) / 1000, total_error / num_samples);
- if (error > alt_error[part])
- alt_error[part] = error;
+ printf ("#define NALT %d\n", dim(alt_part));
+ printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift);
+ printf ("#ifndef AO_ALT_VALUE\n#define AO_ALT_VALUE(x) (alt_t) (x)\n#endif\n");
- total_error += error;
- if (error > max_error) {
- max_error = error;
- max_error_sample = sample;
- }
- if (false) {
- printf (" %8.1f %8.2f %8.2f %8.2f %s\n",
- Pa,
- meters,
- meters_approx,
- meters - meters_approx,
- is_part(sample) ? "*" : "");
+ for (int part = 0; part < dim(alt_part); part++) {
+ real kPa = sample_to_Pa(part_to_sample(part)) / 1000;
+ printf ("AO_ALT_VALUE(%10.1f), /* %6.2f kPa error %6.2fm */\n",
+ round (alt_part[part]*10) / 10, kPa,
+ alt_error[part]);
}
}
-printf ("/*max error %f at %7.3f kPa. Average error %f*/\n",
- max_error, sample_to_Pa(max_error_sample) / 1000, total_error / num_samples);
-
-printf ("#define NALT %d\n", dim(alt_part));
-printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift);
-printf ("#ifndef AO_ALT_VALUE\n#define AO_ALT_VALUE(x) (alt_t) (x)\n#endif\n");
-
-for (int part = 0; part < dim(alt_part); part++) {
- real kPa = sample_to_Pa(part_to_sample(part)) / 1000;
- printf ("AO_ALT_VALUE(%10.1f), /* %6.2f kPa error %6.2fm */\n",
- round (alt_part[part]*10) / 10, kPa,
- alt_error[part]);
+autoload ParseArgs;
+
+void main()
+{
+ /* Target is an array of < 1000 entries */
+ int pa_sample_shift = 2;
+ int pa_part_shift = 6;
+
+ ParseArgs::argdesc argd = {
+ .args = {
+ { .var = { .arg_int = &pa_sample_shift },
+ .abbr = 's',
+ .name = "sample",
+ .expr_name = "sample_shift",
+ .desc = "sample shift value" },
+ { .var = { .arg_int = &pa_part_shift },
+ .abbr = 'p',
+ .name = "part",
+ .expr_name = "part_shift",
+ .desc = "part shift value" },
+ }
+ };
+
+ ParseArgs::parseargs(&argd, &argv);
+
+ print_table(pa_sample_shift, pa_part_shift);
}
+
+main();
TeleGPS-Linux-*.sh
TeleGPS-Mac-*.zip
TeleGPS-Windows-*.exe
-telegps.desktop
+*.desktop
telegps-windows.log
*.dll
*.dylib
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
- <string>TeleGPS.icns</string>
+ <string>altusmetrum-telegps.icns</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>Telemetry</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>application-vnd.altusmetrum.telemetry.icns</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>telem</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>Eeprom</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>application-vnd.altusmetrum.eeprom.icns</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>eeprom</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ </dict>
+ </array>
<key>Java</key>
<dict>
<key>MainClass</key>
ICONDIR=$(top_srcdir)/icon
JAVA_ICONS=\
- $(ICONDIR)/telegps-16.png \
- $(ICONDIR)/telegps-32.png \
- $(ICONDIR)/telegps-48.png \
- $(ICONDIR)/telegps-64.png \
- $(ICONDIR)/telegps-128.png \
- $(ICONDIR)/telegps-256.png
+ $(ICONDIR)/altusmetrum-telegps-16.png \
+ $(ICONDIR)/altusmetrum-telegps-32.png \
+ $(ICONDIR)/altusmetrum-telegps-48.png \
+ $(ICONDIR)/altusmetrum-telegps-64.png \
+ $(ICONDIR)/altusmetrum-telegps-128.png\
+ $(ICONDIR)/altusmetrum-telegps-256.png
# icon base names for jar
-ICONJAR= -C $(ICONDIR) telegps-16.png \
- -C $(ICONDIR) telegps-32.png \
- -C $(ICONDIR) telegps-48.png \
- -C $(ICONDIR) telegps-64.png \
- -C $(ICONDIR) telegps-128.png \
- -C $(ICONDIR) telegps-256.png
-
-WINDOWS_ICON=$(ICONDIR)/telegps.ico
-MACOSX_ICON=$(ICONDIR)/TeleGPS.icns
+ICONJAR= \
+ -C $(ICONDIR) altusmetrum-telegps-16.png \
+ -C $(ICONDIR) altusmetrum-telegps-32.png \
+ -C $(ICONDIR) altusmetrum-telegps-48.png \
+ -C $(ICONDIR) altusmetrum-telegps-64.png \
+ -C $(ICONDIR) altusmetrum-telegps-128.png\
+ -C $(ICONDIR) altusmetrum-telegps-256.png
+
+WINDOWS_ICONS =\
+ ../icon/altusmetrum-telegps.ico \
+ ../icon/altusmetrum-telegps.exe
+ ../icon/application-vnd.altusmetrum.eeprom.ico \
+ ../icon/application-vnd.altusmetrum.eeprom.exe \
+ ../icon/application-vnd.altusmetrum.telemetry.ico \
+ ../icon/application-vnd.altusmetrum.telemetry.exe
+
+MACOSX_ICONS =\
+ ../icon/altusmetrum-telegps.icns \
+ ../icon/application-vnd.altusmetrum.eeprom.icns \
+ ../icon/application-vnd.altusmetrum.telemetry.icns
+
+LINUX_ICONS =\
+ $(ICONDIR)/altusmetrum-altosui.svg \
+ $(ICONDIR)/application-vnd.altusmetrum.eeprom.svg \
+ $(ICONDIR)/application-vnd.altusmetrum.telemetry.svg
+
+LINUX_MIMETYPE =\
+ $(ICONDIR)/org-altusmetrum-mimetypes.xml
# Firmware
FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
FIRMWARE=$(FIRMWARE_TG) $(FIRMWARE_TD) $(FIRMWARE_TBT)
desktopdir = $(datadir)/applications
-desktop_file = telegps.desktop
+desktop_file = altusmetrum-telegps.desktop
desktop_SCRIPTS = $(desktop_file)
all-local: telegps-test telegps-jdb $(JAR)
$(ALTOSUILIB_CLASS) \
$(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt \
telegps telegps-test telegps-jdb macosx linux windows telegps-windows.log \
- telegps-windows.nsi
+ telegps-windows.nsi *.desktop
EXTRA_DIST = $(desktop_file).in
$(desktop_file): $(desktop_file).in
- sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/telegps.desktop.in > $@
+ sed -e 's#%bindir%#@bindir@#' -e 's#%icondir%#$(datadir)/icons/hicolor/scalable/apps#' ${srcdir}/$(desktop_file).in > $@
chmod +x $@
LINUX_DIST=TeleGPS-Linux-$(VERSION).tar.bz2
FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS)
-LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) telegps.desktop.in ../icon/telegps.svg
-LINUX_EXTRA=telegps-fat telegps.desktop.in
+LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) $(desktop_file).in $(LINUX_ICONS) $(LINUX_MIMETYPE)
+LINUX_EXTRA=telegps-fat $(desktop_file).in
MACOSX_INFO_PLIST=Info.plist
MACOSX_README=ReadMe-Mac.rtf
-MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_README) $(DOC) $(MACOSX_ICON)
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_README) $(DOC) $(MACOSX_ICONS)
MACOSX_EXTRA=$(FIRMWARE)
-WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(DOC) $(WINDOWS_ICON)
+WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/altusmetrum.inf $(top_srcdir)/altusmetrum.cat $(DOC) $(WINDOWS_ICONS)
if FATINSTALL
-C classes org \
-C ../libaltos libaltosJNI
-classaltosui.stamp: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS)
-
libaltos.so: build-libaltos
-rm -f "$@"
$(LN_S) ../libaltos/.libs/"$@" .
cp -a $(DOC) macosx/Doc
cp -p Info.plist macosx/TeleGPS.app/Contents
mkdir -p macosx/AltOS-$(VERSION) macosx/TeleGPS.app/Contents/Resources/Java
- cp -p $(MACOSX_ICON) macosx/TeleGPS.app/Contents/Resources
+ cp -p $(MACOSX_ICONS) macosx/TeleGPS.app/Contents/Resources
cp -p $(FATJAR) macosx/TeleGPS.app/Contents/Resources/Java/telegps.jar
cp -p libaltos.dylib macosx/TeleGPS.app/Contents/Resources/Java
cp -p $(ALTOSLIB_CLASS) macosx/TeleGPS.app/Contents/Resources/Java
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class TeleGPS
extends AltosUIFrame
{
static String[] telegps_icon_names = {
- "/telegps-16.png",
- "/telegps-32.png",
- "/telegps-48.png",
- "/telegps-64.png",
- "/telegps-128.png",
- "/telegps-256.png"
+ "/altusmetrum-telegps-16.png",
+ "/altusmetrum-telegps-32.png",
+ "/altusmetrum-telegps-48.png",
+ "/altusmetrum-telegps-64.png",
+ "/altusmetrum-telegps-128.png",
+ "/altusmetrum-telegps-256.png"
};
static { set_icon_names(telegps_icon_names); }
JMenu file_menu;
JMenu monitor_menu;
JMenu device_menu;
- AltosFreqList frequencies;
+ AltosUIFreqList frequencies;
ActionListener frequency_listener;
+ AltosUIRateList rates;
+ ActionListener rate_listener;
Container bag;
telegps_status.disable_receive();
disable_frequency_menu();
+ disable_rate_menu();
}
void connect(AltosDevice device) {
}
+ void enable_rate_menu(int serial, final AltosFlightReader reader) {
+
+ if (rate_listener != null)
+ disable_rate_menu();
+
+ rate_listener = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ int rate = rates.rate();
+ try {
+ System.out.printf("set rate %d\n", rate);
+ reader.set_telemetry_rate(rate);
+ } catch (TimeoutException te) {
+ } catch (InterruptedException ie) {
+ }
+ reader.save_telemetry_rate();
+ }
+ };
+
+ rates.addActionListener(rate_listener);
+ rates.set_product("Monitor");
+ rates.set_serial(serial);
+ rates.set_rate(AltosUIPreferences.telemetry_rate(serial));
+ rates.setEnabled(reader.supports_telemetry_rate(AltosLib.ao_telemetry_rate_2400));
+ }
+
+ void disable_rate_menu() {
+ if (rate_listener != null) {
+ rates.removeActionListener(rate_listener);
+ rates.setEnabled(false);
+ rate_listener = null;
+ }
+
+ }
+
public void set_reader(AltosFlightReader reader, AltosDevice device) {
status_update = new TeleGPSStatusUpdate(telegps_status);
thread = new TeleGPSDisplayThread(this, voice(), this, reader);
thread.start();
- if (device != null)
+ if (device != null) {
enable_frequency_menu(device.getSerial(), reader);
+ enable_rate_menu(device.getSerial(), reader);
+ }
}
static int number_of_windows;
private JMenu make_menu(String label, String[][] items) {
JMenu menu = new JMenu(label);
- for (int i = 0; i < items.length; i++)
+ for (int i = 0; i < items.length; i++) {
+ if (MAC_OS_X) {
+ if (items[i][1].equals("exit"))
+ continue;
+ if (items[i][1].equals("preferences"))
+ continue;
+ }
add_menu(menu, items[i][0], items[i][1]);
+ }
menu_bar.add(menu);
return menu;
}
+ /* OSXAdapter interfaces */
+ public void macosx_file_handler(String path) {
+ process_graph(new File(path));
+ }
+
+ public void macosx_quit_handler() {
+ System.exit(0);
+ }
+
+ public void macosx_preferences_handler() {
+ preferences();
+ }
+
public TeleGPS() {
AltosUIPreferences.set_component(this);
+ register_for_macosx_events();
+
reader = null;
bag = getContentPane();
file_menu = make_menu("File", file_menu_entries);
monitor_menu = make_menu("Monitor", monitor_menu_entries);
device_menu = make_menu("Device", device_menu_entries);
- frequencies = new AltosFreqList();
+
+ frequencies = new AltosUIFreqList();
frequencies.setEnabled(false);
- menu_bar.add(frequencies);
+ c.gridx = 0;
+ c.gridy = 0;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.weightx = 0;
+ c.gridwidth = 1;
+ bag.add(frequencies, c);
+
+ rates = new AltosUIRateList();
+ rates.setEnabled(false);
+ c.gridx = 1;
+ c.gridy = 0;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.weightx = 0;
+ c.gridwidth = 1;
+ bag.add(rates, c);
displays = new LinkedList<AltosFlightDisplay>();
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class TeleGPSConfig implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class TeleGPSConfigUI
extends AltosUIDialog
JLabel radio_calibration_label;
JLabel radio_frequency_label;
JLabel radio_enable_label;
+ JLabel rate_label;
JLabel aprs_interval_label;
+ JLabel aprs_ssid_label;
JLabel flight_log_max_label;
JLabel callsign_label;
JLabel tracker_motion_label;
JLabel product_value;
JLabel version_value;
JLabel serial_value;
- AltosFreqList radio_frequency_value;
+ AltosUIFreqList radio_frequency_value;
JTextField radio_calibration_value;
JRadioButton radio_enable_value;
+ AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
+ JComboBox<Integer> aprs_ssid_value;
JComboBox<String> flight_log_max_value;
JTextField callsign_value;
JComboBox<String> tracker_motion_value;
"10"
};
+ static Integer[] aprs_ssid_values = {
+ 0, 1, 2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+ };
+
static String[] tracker_motion_values_m = {
"2",
"5",
radio_enable_value.setToolTipText("Firmware version does not support disabling radio");
}
+ void set_rate_tool_tip() {
+ if (rate_value.isEnabled())
+ rate_value.setToolTipText("Select telemetry baud rate");
+ else
+ rate_value.setToolTipText("Firmware version does not support variable telemetry rates");
+ }
+
void set_aprs_interval_tool_tip() {
if (aprs_interval_value.isEnabled())
aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports");
aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
}
+ void set_aprs_ssid_tool_tip() {
+ if (aprs_ssid_value.isEnabled())
+ aprs_interval_value.setToolTipText("Set the APRS SSID (secondary station identifier)");
+ else if (aprs_interval_value.isEnabled())
+ aprs_interval_value.setToolTipText("Software version doesn't support setting the APRS SSID");
+ else
+ aprs_interval_value.setToolTipText("Hardware doesn't support APRS");
+ }
+
void set_flight_log_max_tool_tip() {
if (flight_log_max_value.isEnabled())
flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)");
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_frequency_value = new AltosFreqList();
+ radio_frequency_value = new AltosUIFreqList();
radio_frequency_value.addItemListener(this);
pane.add(radio_frequency_value, c);
radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency");
set_radio_enable_tool_tip();
row++;
+ /* Telemetry Rate */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ rate_label = new JLabel("Telemetry baud rate:");
+ pane.add(radio_enable_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ rate_value = new AltosUIRateList();
+ rate_value.addItemListener(this);
+ pane.add(rate_value, c);
+ set_rate_tool_tip();
+ row++;
+
/* APRS interval */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = row;
set_aprs_interval_tool_tip();
row++;
+ /* APRS SSID */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ aprs_ssid_label = new JLabel("APRS SSID:");
+ pane.add(aprs_ssid_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 4; c.gridy = row;
+ c.gridwidth = 4;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ aprs_ssid_value = new JComboBox<Integer>(aprs_ssid_values);
+ aprs_ssid_value.setEditable(false);
+ aprs_ssid_value.addItemListener(this);
+ aprs_ssid_value.setMaximumRowCount(aprs_ssid_values.length);
+ pane.add(aprs_ssid_value, c);
+ set_aprs_ssid_tool_tip();
+ row++;
+
/* Callsign */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = row;
}
public void units_changed(boolean imperial_units) {
+ boolean was_dirty = dirty;
+
if (tracker_motion_value.isEnabled()) {
String motion = tracker_motion_value.getSelectedItem().toString();
tracker_motion_label.setText(get_tracker_motion_label());
set_tracker_motion_values();
set_tracker_motion((int) (AltosConvert.height.parse(motion, !imperial_units) + 0.5));
}
+ if (!was_dirty)
+ set_clean();
}
/* set and get all of the dialog values */
serial_value.setText(String.format("%d", serial));
}
+ public void set_altitude_32(int altitude_32) {
+ }
+
public void set_main_deploy(int new_main_deploy) {
}
return -1;
}
+ public void set_telemetry_rate(int new_rate) {
+ rate_value.set_rate(new_rate);
+ }
+
+ public int telemetry_rate() {
+ return rate_value.rate();
+ }
+
public void set_callsign(String new_callsign) {
callsign_value.setVisible(new_callsign != null);
callsign_value.setText(new_callsign);
}
public void set_tracker_motion(int tracker_motion) {
- tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
+ if (tracker_motion < 0) {
+ tracker_motion_value.setEnabled(false);
+ } else {
+ tracker_motion_value.setEnabled(true);
+ tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion));
+ }
}
public int tracker_motion() throws AltosConfigDataException {
}
public void set_tracker_interval(int tracker_interval) {
- tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
+ if (tracker_interval< 0) {
+ tracker_interval_value.setEnabled(false);
+ } else {
+ tracker_interval_value.setEnabled(true);
+ tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval));
+ }
}
public int tracker_interval() throws AltosConfigDataException {
return 0;
return parse_int("aprs interval", s, false);
}
+
+ public void set_aprs_ssid(int new_aprs_ssid) {
+ aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid));
+ aprs_ssid_value.setVisible(new_aprs_ssid >= 0);
+ set_aprs_ssid_tool_tip();
+ }
+
+ public int aprs_ssid() throws AltosConfigDataException {
+ Integer i = (Integer) aprs_ssid_value.getSelectedItem();
+ return i;
+ }
}
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class TeleGPSDisplayThread extends Thread {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class TeleGPSInfo extends AltosUIFlightTab {
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altosuilib_3.*;
public class TeleGPSPreferences
extends AltosUIConfigure
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class TeleGPSState extends AltosUIFlightTab {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_4.*;
-import org.altusmetrum.altosuilib_2.*;
+import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altosuilib_3.*;
public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
package org.altusmetrum.telegps;
import java.awt.event.*;
-import org.altusmetrum.altoslib_4.*;
+import org.altusmetrum.altoslib_5.*;
public class TeleGPSStatusUpdate implements ActionListener {
--- /dev/null
+[Desktop Entry]
+Type=Application
+Name=TeleGPS
+GenericName=TeleGPS monitor, download and analysis
+Comment=View and log data from TeleGPS tracking devices
+Icon=%icondir%/altusmetrum-telegps.svg
+Exec=%bindir%/telegps %f
+Terminal=false
+MimeType=application/vnd.altusmetrum.telemetry;application/vnd.altusmetrum.eeprom
+Categories=Education;Electronics;Science;
!addincludedir ../altosui/Instdrv/NSIS/Includes
!include x64.nsh
!include java.nsh
+!include refresh-sh.nsh
-Name "TeleGPS Installer"
+!define REG_NAME "TeleGPS"
+!define PROG_ID_TELEM "altusmetrum.telegps.telem.1"
+!define PROG_ID_EEPROM "altusmetrum.telegps.eeprom.1"
+!define FAT_NAME "telegps-fat.jar"
+!define WIN_APP_ICON "altusmetrum-telegps.ico"
+!define WIN_APP_EXE "altusmetrum-telegps.exe"
+!define WIN_TELEM_EXE "application-vnd.altusmetrum.telemetry.exe"
+!define WIN_EEPROM_EXE "application-vnd.altusmetrum.eeprom.exe"
+
+Name "${REG_NAME} Installer"
; Default install directory
InstallDir "$PROGRAMFILES\AltusMetrum"
; Tell the installer where to re-install a new version
-InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+InstallDirRegKey HKLM "Software\${REG_NAME}" "Install_Dir"
LicenseText "GNU General Public License Version 2"
LicenseData "../COPYING"
ShowInstDetails Show
-ComponentText "TeleGPS Software Installer"
+ComponentText "${REG_NAME} Software and Driver Installer"
Function .onInit
DetailPrint "Checking host operating system"
${EndIf}
FunctionEnd
+Function un.onInit
+ DetailPrint "Checking host operating system"
+ ${If} ${RunningX64}
+ DetailPrint "Installer running on 64-bit host"
+ SetRegView 64
+ StrCpy $INSTDIR "$PROGRAMFILES64\AltusMetrum"
+ ${DisableX64FSRedirection}
+ ${EndIf}
+FunctionEnd
+
; Pages to present
Page license
SectionEnd
-Section "TeleGPS Application"
+Section "${REG_NAME} Application"
Call DetectJRE
SetOutPath $INSTDIR
- File "telegps-fat.jar"
+ File "${FAT_NAME}"
File "altoslib_@ALTOSLIB_VERSION@.jar"
File "altosuilib_@ALTOSUILIB_VERSION@.jar"
File "cmudict04.jar"
File "*.dll"
- File "../icon/*.ico"
+ File "../icon/${WIN_APP_ICON}"
- CreateShortCut "$SMPROGRAMS\TeleGPS.lnk" "$SYSDIR\javaw.exe" "-jar telegps-fat.jar" "$INSTDIR\telegps.ico"
+ CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
-Section "TeleGPS Desktop Shortcut"
- CreateShortCut "$DESKTOP\TeleGPS.lnk" "$INSTDIR\telegps-fat.jar" "" "$INSTDIR\telegps.ico"
+Section "${REG_NAME} Desktop Shortcut"
+ CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
Section "TeleGPS, TeleDongle and TeleBT Firmware"
File "../doc/telemetry.pdf"
SectionEnd
+Section "File Associations"
+
+ ${DisableX64FSRedirection}
+
+ SetOutPath $INSTDIR
+
+ File "../icon/${WIN_APP_EXE}"
+ File "../icon/${WIN_TELEM_EXE}"
+ File "../icon/${WIN_EEPROM_EXE}"
+
+ DeleteRegKey HKCR "${PROG_ID_TELEM}"
+ DeleteRegKey HKCR "${PROG_ID_EEPROM}"
+
+ DeleteRegKey HKCR ".eeprom\${PROG_ID_EEPROM}"
+ DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
+ DeleteRegKey HKCR ".telem\${PROG_ID_EEPROM}"
+ DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
+
+ ; .eeprom elements
+
+ WriteRegStr HKCR "${PROG_ID_EEPROM}" "" "Altus Metrum Log File"
+ WriteRegStr HKCR "${PROG_ID_EEPROM}" "FriendlyTypeName" "Altus Metrum Log File"
+ WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer" "" "${PROG_ID_EEPROM}"
+ WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" "" '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
+ WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+ WriteRegStr HKCR ".eeprom" "" "${PROG_ID_EEPROM}"
+ WriteRegStr HKCR ".eeprom" "PerceivedType" "Altus Metrum Log File"
+ WriteRegStr HKCR ".eeprom" "Content Type" "application/vnd.altusmetrum.eeprom"
+
+ WriteRegStr HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}" ""
+ WriteRegStr HKCR ".eeprom\${PROG_ID_EEPROM}" "" "${REG_NAME}"
+
+ ; .telem elements
+
+ WriteRegStr HKCR "${PROG_ID_TELEM}" "" "Altus Metrum Telemetry File"
+ WriteRegStr HKCR "${PROG_ID_TELEM}" "FriendlyTypeName" "Altus Metrum Telemetry File"
+ WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer" "" "${PROG_ID_TELEM}"
+ WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" "" '"$INSTDIR\${WIN_TELEM_EXE}",-101'
+ WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+
+ WriteRegStr HKCR ".telem" "" "${PROG_ID_TELEM}"
+ WriteRegStr HKCR ".telem" "PerceivedType" "Altus Metrum Telemetry File"
+ WriteRegStr HKCR ".telem" "Content Type" "application/vnd.altusmetrum.telemetry"
+
+ WriteRegStr HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}" ""
+ WriteRegStr HKCR ".telem\${PROG_ID_TELEM}" "" "${REG_NAME}"
+
+ Call RefreshShellIcons
+SectionEnd
+
Section "Uninstaller"
; Deal with the uninstaller
+ ${DisableX64FSRedirection}
SetOutPath $INSTDIR
; Write the install path to the registry
- WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR"
+ WriteRegStr HKLM "SOFTWARE\${REG_NAME}" "Install_Dir" "$INSTDIR"
; Write the uninstall keys for windows
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"'
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "DisplayName" "${REG_NAME}"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "UninstallString" '"$INSTDIR\uninstall-${REG_NAME}.exe"'
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoModify" "1"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}" "NoRepair" "1"
- WriteUninstaller "uninstall.exe"
+ WriteUninstaller "uninstall-${REG_NAME}.exe"
SectionEnd
Section "Uninstall"
- DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
- DeleteRegKey HKLM "Software\AltusMetrum"
- Delete "$INSTDIR\*.*"
- RMDir "$INSTDIR"
+ ${DisableX64FSRedirection}
- ; Remove devices
- InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
- InstDrv::DeleteOemInfFiles /NOUNLOAD
- InstDrv::RemoveAllDevices
+ DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${REG_NAME}"
+ DeleteRegKey HKLM "SOFTWARE\${REG_NAME}"
+
+ DetailPrint "Delete uninstall reg entries"
+
+ DeleteRegKey HKCR "${PROG_ID_EEPROM}"
+ DeleteRegKey HKCR "${PROG_ID_TELEM}"
+
+ DeleteRegKey HKCR ".eeprom\${PROG_ID_EEPROM}"
+ DeleteRegValue HKCR ".eeprom\OpenWithProgids" "${PROG_ID_EEPROM}"
+
+ DeleteRegKey HKCR ".telem\${PROG_ID_TELEM}"
+ DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_TELEM}"
+
+ DetailPrint "Delete file association reg entries"
+
+ Delete "$INSTDIR\${FAT_NAME}"
+ Delete "$INSTDIR\uninstall-${REG_NAME}.exe"
+
+ Delete "$INSTDIR\${WIN_APP_ICON}"
+ Delete "$INSTDIR\${WIN_APP_EXE}"
; Remove shortcuts, if any
- Delete "$SMPROGRAMS\TeleGPS.lnk"
- Delete "$DESKTOP\TeleGPS.lnk"
+ Delete "$SMPROGRAMS\${REG_NAME}.lnk"
+ Delete "$DESKTOP\${REG_NAME}.lnk"
+ Call un.RefreshShellIcons
SectionEnd
+++ /dev/null
-[Desktop Entry]
-Type=Application
-Name=TeleGPS
-GenericName=TeleGPS monitor, download and analysis
-Comment=View and log data from TeleGPS tracking devices
-Icon=%icondir%/telegps.svg
-Exec=%bindir%/telegps %f
-Terminal=false
-MimeType=text/plain;
-Categories=Education;Electronics;Science;