diff options
author | Bdale Garbee <bdale@gag.com> | 2014-09-09 23:28:39 -0600 |
---|---|---|
committer | Bdale Garbee <bdale@gag.com> | 2014-09-09 23:28:39 -0600 |
commit | 16405fd3eb6f82ef3a709e3ed30fc48faef7b547 (patch) | |
tree | c111819b3ba0c9357af41c81b798326b9df7adad | |
parent | 5a2f6ed6210844f7284fbf9f7ecba68c8a14fa52 (diff) | |
parent | 28bd5057252e61bc5b1a35a00bc1f9fdfde097f7 (diff) |
Merge branch 'branch-1.5' into debian
Conflicts:
ChangeLog
Releasing
altosui/Instdrv/NSIS/Includes/java.nsh
altosui/altos-windows.nsi.in
configure.ac
doc/Makefile
doc/altusmetrum.xsl
micropeak/micropeak-windows.nsi.in
telegps/telegps-windows.nsi.in
423 files changed, 11199 insertions, 1985 deletions
@@ -1,45 +1,1237 @@ -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: Tue Jun 24 21:31:53 2014 -0600 +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> - Merge branch 'branch-1.4' of ssh://git.gag.com/scm/git/fw/altos into branch-1.4 +commit f395bcaa620490954d4a42de9b4870bc12bedc91 +Author: Keith Packard <keithp@keithp.com> +Date: Sat Sep 6 20:39:37 2014 -0700 -commit 5f6059a9273dfe557145a9f620db81693f3bc27e + 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: Tue Jun 24 21:22:26 2014 -0600 +Date: Sat Sep 6 13:41:36 2014 -0600 - need the api key in Bdale's root too + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + + Conflicts: + ao-bringup/turnon_telemega -commit 42fd93b67af396b0478e9e795026cf1a5312e5c9 +commit e9714e34091abe657aa1b30aeda9466331aa39c1 Author: Bdale Garbee <bdale@gag.com> -Date: Tue Jun 24 21:12:59 2014 -0600 +Date: Sat Sep 6 13:40:59 2014 -0600 - make sure to use Google Maps API key for official builds + 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 -commit 9a78df4ea121d1d3c14da2abae1a82c34121e13c + 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: Sun Jun 15 18:41:25 2014 -0600 +Date: Mon Aug 18 11:25:32 2014 -0600 - notes updated for TeleGPS and 1.4 release learnings + turn echo back on after accel cal in turnon_telemetrum so rest is easier -commit 237472e1b98283a82c674bb48c0347189d9d37bf +commit 44e389c31e5958c1a050fbe0dce5d7971a9d6a86 Author: Keith Packard <keithp@keithp.com> -Date: Tue Jun 24 20:15:38 2014 -0700 +Date: Sun Aug 17 21:03:12 2014 -0700 - altosuilib: Mark 'Configure AltosUI' window with maps key status + altos: Add telerepeat-v1.0 - This lets us check a build to make sure it has a maps key + 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 0da9cdfbeacbaed13615ca2daade372920299c4a +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> + +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 505c6a1f8b8d68fe6f74dcb4428c860157fae3de +Author: Bdale Garbee <bdale@gag.com> +Date: Wed Jun 25 13:37:56 2014 -0600 + + note need to push the updated repo with production binaries during release + +commit 75db560e2c9fbb2889db507acc93e889bf15bc2a +Author: Bdale Garbee <bdale@gag.com> +Date: Tue Jun 24 22:43:04 2014 -0600 + + Windows sucks, hard .. make sure filenames are legal in .mdwn files + +commit 61ca8493566d5ea0da379970ab94f80a462dd368 +Author: Bdale Garbee <bdale@gag.com> +Date: Tue Jun 24 22:35:43 2014 -0600 + + update Releasing file based on learnings from 1.4.1 release + +commit 424112349d54bb6360403683f8012b83f49220be +Author: Keith Packard <keithp@keithp.com> +Date: Tue Jun 24 20:57:29 2014 -0700 + + telegps: Disable tracker config when not available + + 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 6cb5955ab5aa3b42a507c4a02812cb5569b8562b Author: Keith Packard <keithp@keithp.com> Date: Fri Jun 20 11:56:58 2014 -0700 @@ -47,7 +1239,7 @@ 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 @@ -55,7 +1247,236 @@ 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 @@ -63,7 +1484,43 @@ 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 @@ -77,7 +1534,7 @@ 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 @@ -88,6 +1545,84 @@ 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 diff --git a/Makefile.am b/Makefile.am index 15d2c82d..2f8a5ee1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,6 +18,7 @@ fat: 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 @@ -1,5 +1,8 @@ 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 @@ -75,6 +78,7 @@ These are Bdale's notes on how to do a release. 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> @@ -87,9 +91,9 @@ These are Bdale's notes on how to do a release. - 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) diff --git a/altosdroid/Notebook b/altosdroid/Notebook index ebb3578d..5a4df032 100644 --- a/altosdroid/Notebook +++ b/altosdroid/Notebook @@ -8,6 +8,8 @@ Desired AltosDroid feature list *) Highlight current frequency in the frequency list. + Placed current frequency in title bar + *) Random frequency selection. Provide some mechanism to input arbitrary radio frequencies. Could be like AltosUI which allows you to edit the list of frequencies and assign names to them, @@ -23,10 +25,16 @@ Desired AltosDroid feature list *) 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 diff --git a/altosdroid/res/layout/device_list.xml b/altosdroid/res/layout/device_list.xml index 395695f8..93d65517 100644 --- a/altosdroid/res/layout/device_list.xml +++ b/altosdroid/res/layout/device_list.xml @@ -18,39 +18,39 @@ 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> diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml index d7ba8305..3bd5a54e 100644 --- a/altosdroid/res/menu/option_menu.xml +++ b/altosdroid/res/menu/option_menu.xml @@ -17,7 +17,16 @@ <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> diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 90da617b..0cc99349 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -22,12 +22,15 @@ <!-- 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> diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 1b4d45ed..51ef5e94 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -31,7 +31,7 @@ import android.os.Handler; //import android.os.Message; import android.util.Log; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosBluetooth extends AltosLink { @@ -52,6 +52,7 @@ 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; @@ -136,9 +137,27 @@ public class AltosBluetooth extends AltosLink { } } + 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(); } } @@ -174,18 +193,29 @@ public class AltosBluetooth extends AltosLink { } 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() { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index f61baf1e..f6cceac9 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -37,35 +37,40 @@ import android.os.Message; 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; @@ -75,12 +80,16 @@ public class AltosDroid extends FragmentActivity { 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; @@ -89,23 +98,14 @@ public class AltosDroid extends FragmentActivity { 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; @@ -117,38 +117,21 @@ public class AltosDroid extends FragmentActivity { @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; } } @@ -204,57 +187,180 @@ public class AltosDroid extends FragmentActivity { 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() { @@ -301,12 +407,9 @@ public class AltosDroid extends FragmentActivity { 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); @@ -349,7 +452,6 @@ public class AltosDroid extends FragmentActivity { 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); @@ -365,11 +467,10 @@ public class AltosDroid extends FragmentActivity { 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); } @@ -378,15 +479,16 @@ public class AltosDroid extends FragmentActivity { 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 @@ -415,6 +517,7 @@ public class AltosDroid extends FragmentActivity { if(D) Log.e(TAG, "--- ON DESTROY ---"); if (mAltosVoice != null) mAltosVoice.stop(); + stop_timer(); } public void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -442,19 +545,21 @@ public class AltosDroid extends FragmentActivity { } } - 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(); @@ -476,6 +581,33 @@ public class AltosDroid extends FragmentActivity { } } + 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; @@ -485,6 +617,11 @@ public class AltosDroid extends FragmentActivity { 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 @@ -501,16 +638,40 @@ public class AltosDroid extends FragmentActivity { "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; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java index f6e6881d..9cef1319 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java @@ -1,5 +1,5 @@ /* - * 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 @@ -14,88 +14,38 @@ * 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; + } } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java new file mode 100644 index 00000000..be41ae7c --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java @@ -0,0 +1,101 @@ +/* + * 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(); + } +} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java index fac4b8d4..8e625da6 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -17,9 +17,67 @@ 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; + } + } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java index 5e8515cb..969992d3 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java @@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid; import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech.OnInitListener; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosVoice { @@ -45,7 +45,7 @@ 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); } @@ -58,7 +58,7 @@ public class AltosVoice { } } - public void tell(AltosState state) { + public void tell(AltosState state, AltosGreatCircle from_receiver) { if (!tts_enabled) return; boolean spoke = false; @@ -68,12 +68,14 @@ public class AltosVoice { 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; } } @@ -87,13 +89,15 @@ public class AltosVoice { } } 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; @@ -111,22 +115,30 @@ public class AltosVoice { 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; } @@ -145,9 +157,9 @@ public class AltosVoice { 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; } } @@ -178,9 +190,10 @@ public class AltosVoice { } } - 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(); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java b/altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java index 8e8d9c03..267c90f8 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java @@ -20,6 +20,7 @@ package org.altusmetrum.AltosDroid; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.widget.ImageView; +import android.view.View; public class GoNoGoLights { private Boolean state; @@ -51,14 +52,27 @@ public class GoNoGoLights { 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); + } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java index e4a815eb..fa4e3c8b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; import android.app.Activity; import android.os.Bundle; @@ -29,7 +29,7 @@ import android.widget.ImageView; 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; @@ -85,14 +85,19 @@ public class TabAscent extends Fragment implements AltosDroidTab { 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")); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java index cbbe4d44..28068666 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; import android.app.Activity; import android.os.Bundle; @@ -29,7 +29,7 @@ import android.widget.ImageView; 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; @@ -89,16 +89,18 @@ public class TabDescent extends Fragment implements AltosDroidTab { 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>"); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java index b2e6fd20..b257b936 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; import android.app.Activity; import android.os.Bundle; @@ -28,7 +28,7 @@ import android.view.ViewGroup; 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; @@ -73,10 +73,12 @@ public class TabLanded extends Fragment implements AltosDroidTab { 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")); @@ -87,12 +89,11 @@ public class TabLanded extends Fragment implements AltosDroidTab { 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()); } } - } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java index 38922771..ab338ac2 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java @@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid; 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; @@ -42,7 +42,7 @@ import android.view.ViewGroup; 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; @@ -51,6 +51,7 @@ public class TabMap extends Fragment implements AltosDroidTab { private Marker mRocketMarker; private Marker mPadMarker; + private boolean pad_set; private Polyline mPolyline; private TextView mDistanceView; @@ -152,10 +153,12 @@ public class TabMap extends Fragment implements AltosDroidTab { } } - 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) { @@ -168,7 +171,8 @@ public class TabMap extends Fragment implements AltosDroidTab { 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); } @@ -194,5 +198,4 @@ public class TabMap extends Fragment implements AltosDroidTab { } } - } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java index 2d88974d..32df71d7 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; import android.app.Activity; import android.os.Bundle; @@ -29,14 +29,17 @@ import android.widget.ImageView; 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; @@ -59,16 +62,19 @@ public class TabPad extends Fragment implements AltosDroidTab { 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()); @@ -101,15 +107,29 @@ public class TabPad extends Fragment implements AltosDroidTab { 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) { @@ -139,12 +159,12 @@ public class TabPad extends Fragment implements AltosDroidTab { } 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); } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java index a4758c37..1ac34f9d 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabsAdapter.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; @@ -28,8 +29,7 @@ import android.view.View; 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 @@ -48,11 +48,13 @@ public class TabsAdapter extends FragmentPagerAdapter 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; @@ -104,11 +106,32 @@ public class TabsAdapter extends FragmentPagerAdapter @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); } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java index 4215a330..49bcfb88 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java @@ -1,6 +1,6 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java index 5bc4b90d..971c3e80 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java @@ -25,12 +25,13 @@ import java.util.concurrent.*; 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; @@ -39,6 +40,8 @@ public class TelemetryReader extends Thread { AltosLink link; AltosState state = null; + AltosFlightReader stacked; + LinkedBlockingQueue<AltosLine> telemQueue; public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException { @@ -56,6 +59,10 @@ public class TelemetryReader extends Thread { public void close() { state = null; + if (stacked != null) { + stacked.close(false); + stacked = null; + } link.remove_monitor(telemQueue); link = null; telemQueue.clear(); @@ -66,7 +73,27 @@ public class TelemetryReader extends Thread { 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(); @@ -84,12 +111,34 @@ public class TelemetryReader extends Thread { } } - 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)); } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index da5e044f..30d94409 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -28,6 +28,7 @@ import android.app.Notification; 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; @@ -44,7 +45,7 @@ import android.location.LocationManager; 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 { @@ -61,11 +62,7 @@ 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. @@ -80,21 +77,17 @@ public class TelemetryService extends Service implements LocationListener { 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; @@ -103,17 +96,15 @@ public class TelemetryService extends Service implements LocationListener { @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); } @@ -125,42 +116,59 @@ public class TelemetryService extends Service implements LocationListener { 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); @@ -168,9 +176,18 @@ public class TelemetryService extends Service implements LocationListener { } } - 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); @@ -180,7 +197,7 @@ public class TelemetryService extends Service implements LocationListener { 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(); @@ -200,18 +217,21 @@ public class TelemetryService extends Service implements LocationListener { 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 @@ -219,28 +239,19 @@ public class TelemetryService extends Service implements LocationListener { // ... 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. @@ -248,19 +259,25 @@ public class TelemetryService extends Service implements LocationListener { 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) { @@ -271,19 +288,35 @@ public class TelemetryService extends Service implements LocationListener { @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 @@ -339,8 +372,9 @@ public class TelemetryService extends Service implements LocationListener { 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) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java new file mode 100644 index 00000000..d3341739 --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java @@ -0,0 +1,46 @@ +/* + * 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); + } +} diff --git a/altoslib/AltosAccel.java b/altoslib/AltosAccel.java index 3d340e5d..d91da4da 100644 --- a/altoslib/AltosAccel.java +++ b/altoslib/AltosAccel.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosAccel extends AltosUnits { diff --git a/altoslib/AltosCRCException.java b/altoslib/AltosCRCException.java index 253ca435..507c446b 100644 --- a/altoslib/AltosCRCException.java +++ b/altoslib/AltosCRCException.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosCRCException extends Exception { public int rssi; diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java index 27e1fade..4a9278d9 100644 --- a/altoslib/AltosCSV.java +++ b/altoslib/AltosCSV.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -29,6 +29,14 @@ public class AltosCSV implements AltosWriter { 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: @@ -55,10 +63,12 @@ public class AltosCSV implements AltosWriter { * 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²) @@ -87,7 +97,9 @@ public class AltosCSV implements AltosWriter { * 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 @@ -107,7 +119,7 @@ public class AltosCSV implements AltosWriter { 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); } @@ -121,11 +133,11 @@ public class AltosCSV implements AltosWriter { } 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(), @@ -133,11 +145,18 @@ public class AltosCSV implements AltosWriter { 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"); } @@ -150,14 +169,14 @@ public class AltosCSV implements AltosWriter { 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) { @@ -169,7 +188,7 @@ public class AltosCSV implements AltosWriter { 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, @@ -186,7 +205,9 @@ public class AltosCSV implements AltosWriter { state.range, from_pad.bearing, state.elevation, - gps.hdop); + gps.pdop, + gps.hdop, + gps.vdop); } void write_gps_sat_header() { @@ -239,52 +260,83 @@ public class AltosCSV implements AltosWriter { 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) { @@ -300,7 +352,7 @@ public class AltosCSV implements AltosWriter { pad_states.add(state); } - public PrintStream out() { + private PrintStream out() { return out; } @@ -314,6 +366,31 @@ public class AltosCSV implements AltosWriter { 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); } diff --git a/altoslib/AltosCompanion.java b/altoslib/AltosCompanion.java index 09bfe9f3..47deb2a3 100644 --- a/altoslib/AltosCompanion.java +++ b/altoslib/AltosCompanion.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosCompanion { public final static int board_id_telescience = 0x0a; diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index e1043958..fc1f2442 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.*; import java.text.*; @@ -31,6 +31,7 @@ public class AltosConfigData implements Iterable<String> { public int log_format; public int log_space; public String version; + public int altitude_32; /* Strings returned */ public LinkedList<String> lines; @@ -46,6 +47,7 @@ public class AltosConfigData implements Iterable<String> { 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; @@ -56,6 +58,7 @@ public class AltosConfigData implements Iterable<String> { /* HAS_LOG */ public int flight_log_max; + public int log_fixed; /* HAS_IGNITE */ public int ignite_mode; @@ -71,6 +74,7 @@ public class AltosConfigData implements Iterable<String> { /* HAS_APRS */ public int aprs_interval; + public int aprs_ssid; /* HAS_BEEP */ public int beep; @@ -234,12 +238,14 @@ public class AltosConfigData implements Iterable<String> { 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 = ""; @@ -250,6 +256,7 @@ public class AltosConfigData implements Iterable<String> { pyro_firing_time = -1; aprs_interval = -1; + aprs_ssid = -1; beep = -1; @@ -270,6 +277,7 @@ public class AltosConfigData implements Iterable<String> { 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 */ @@ -290,6 +298,7 @@ public class AltosConfigData implements Iterable<String> { 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) {} @@ -309,6 +318,7 @@ public class AltosConfigData implements Iterable<String> { /* 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) {} @@ -333,6 +343,7 @@ public class AltosConfigData implements Iterable<String> { /* 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) {} @@ -375,6 +386,10 @@ public class AltosConfigData implements Iterable<String> { 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; @@ -414,6 +429,8 @@ public class AltosConfigData implements Iterable<String> { return false; if (product.startsWith("TeleMetrum-v2")) return false; + if (product.startsWith("EasyMega")) + return false; return true; } @@ -437,6 +454,8 @@ public class AltosConfigData implements Iterable<String> { 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) @@ -459,6 +478,8 @@ public class AltosConfigData implements Iterable<String> { /* 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) @@ -474,16 +495,21 @@ public class AltosConfigData implements Iterable<String> { 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; @@ -507,6 +533,7 @@ public class AltosConfigData implements Iterable<String> { 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); @@ -537,14 +564,36 @@ public class AltosConfigData implements Iterable<String> { 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); @@ -577,6 +626,8 @@ public class AltosConfigData implements Iterable<String> { /* 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) diff --git a/altoslib/AltosConfigDataException.java b/altoslib/AltosConfigDataException.java index ae5621cc..a932d3e3 100644 --- a/altoslib/AltosConfigDataException.java +++ b/altoslib/AltosConfigDataException.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosConfigDataException extends Exception { diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java index 724ba7dc..3f0a7075 100644 --- a/altoslib/AltosConfigValues.java +++ b/altoslib/AltosConfigValues.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public interface AltosConfigValues { /* set and get all of the dialog values */ @@ -25,6 +25,8 @@ public interface AltosConfigValues { 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; @@ -53,6 +55,10 @@ public interface AltosConfigValues { 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); @@ -81,6 +87,10 @@ public interface AltosConfigValues { 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); diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index dc0fbb62..18878c02 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -18,7 +18,7 @@ /* * Sensor data conversion functions */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosConvert { /* diff --git a/altoslib/AltosDebug.java b/altoslib/AltosDebug.java index b0e52fc1..e58fbaf2 100644 --- a/altoslib/AltosDebug.java +++ b/altoslib/AltosDebug.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; @@ -52,7 +52,7 @@ public class AltosDebug { public static final byte GET_CHIP_ID = 0x68; - AltosLink link; + private AltosLink link; boolean debug_mode; @@ -112,7 +112,11 @@ public class AltosDebug { 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 @@ -277,4 +281,4 @@ public class AltosDebug { public AltosDebug (AltosLink link) { this.link = link; } -}
\ No newline at end of file +} diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java index 76ca20c0..67bb58e9 100644 --- a/altoslib/AltosDistance.java +++ b/altoslib/AltosDistance.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosDistance extends AltosUnits { diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java index 020590eb..532c9f1d 100644 --- a/altoslib/AltosEeprom.java +++ b/altoslib/AltosEeprom.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java index 91eebc5a..4d12f564 100644 --- a/altoslib/AltosEepromChunk.java +++ b/altoslib/AltosEepromChunk.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java index a2dfc438..a448ee64 100644 --- a/altoslib/AltosEepromDownload.java +++ b/altoslib/AltosEepromDownload.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index b7e446ce..a1579b55 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromGPS.java b/altoslib/AltosEepromGPS.java index 3c1852c0..8c991a6e 100644 --- a/altoslib/AltosEepromGPS.java +++ b/altoslib/AltosEepromGPS.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -37,7 +37,7 @@ public class AltosEepromGPS extends AltosEeprom { /* 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); } @@ -52,6 +52,7 @@ public class AltosEepromGPS extends AltosEeprom { 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; } @@ -90,8 +91,10 @@ public class AltosEepromGPS extends AltosEeprom { 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: @@ -99,7 +102,10 @@ public class AltosEepromGPS extends AltosEeprom { 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(); @@ -118,8 +124,21 @@ public class AltosEepromGPS extends AltosEeprom { 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; } } diff --git a/altoslib/AltosEepromHeader.java b/altoslib/AltosEepromHeader.java index 839aa06e..71030655 100644 --- a/altoslib/AltosEepromHeader.java +++ b/altoslib/AltosEepromHeader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -96,6 +96,22 @@ public class AltosEepromHeader extends AltosEeprom { 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; } } @@ -161,6 +177,22 @@ public class AltosEepromHeader extends AltosEeprom { 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; } } @@ -205,6 +237,9 @@ public class AltosEepromHeader extends AltosEeprom { } 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]; diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java index d6832c1b..dd0afd9f 100644 --- a/altoslib/AltosEepromIterable.java +++ b/altoslib/AltosEepromIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java index ab853a88..740499d3 100644 --- a/altoslib/AltosEepromList.java +++ b/altoslib/AltosEepromList.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java index 1a430c03..5a11fa54 100644 --- a/altoslib/AltosEepromLog.java +++ b/altoslib/AltosEepromLog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java index 71719a26..adaa7f31 100644 --- a/altoslib/AltosEepromMega.java +++ b/altoslib/AltosEepromMega.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -67,7 +67,7 @@ public class AltosEepromMega extends AltosEeprom { /* 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); } @@ -82,6 +82,7 @@ public class AltosEepromMega extends AltosEeprom { 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); } @@ -168,7 +169,11 @@ public class AltosEepromMega extends AltosEeprom { 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(); @@ -187,8 +192,21 @@ public class AltosEepromMega extends AltosEeprom { 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); diff --git a/altoslib/AltosEepromMetrum2.java b/altoslib/AltosEepromMetrum2.java index d137614a..d9a65989 100644 --- a/altoslib/AltosEepromMetrum2.java +++ b/altoslib/AltosEepromMetrum2.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -49,7 +49,8 @@ public class AltosEepromMetrum2 extends AltosEeprom { /* 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); } @@ -59,6 +60,7 @@ public class AltosEepromMetrum2 extends AltosEeprom { 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); } @@ -117,7 +119,10 @@ public class AltosEepromMetrum2 extends AltosEeprom { 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); @@ -136,6 +141,7 @@ public class AltosEepromMetrum2 extends AltosEeprom { 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); diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java index 32985639..f197539e 100644 --- a/altoslib/AltosEepromMini.java +++ b/altoslib/AltosEepromMini.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromMonitor.java b/altoslib/AltosEepromMonitor.java index b97287c3..173a2cd8 100644 --- a/altoslib/AltosEepromMonitor.java +++ b/altoslib/AltosEepromMonitor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public interface AltosEepromMonitor { diff --git a/altoslib/AltosEepromTM.java b/altoslib/AltosEepromTM.java index 77fe20c5..6d36cf47 100644 --- a/altoslib/AltosEepromTM.java +++ b/altoslib/AltosEepromTM.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromTm.java b/altoslib/AltosEepromTm.java index 6cbb7253..81b42f21 100644 --- a/altoslib/AltosEepromTm.java +++ b/altoslib/AltosEepromTm.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java index 2a738996..ba639a04 100644 --- a/altoslib/AltosFile.java +++ b/altoslib/AltosFile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.File; import java.util.*; diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java index 8e8722c2..a8519550 100644 --- a/altoslib/AltosFlash.java +++ b/altoslib/AltosFlash.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; @@ -345,9 +345,23 @@ public class AltosFlash extends AltosProgrammer { 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 +} diff --git a/altoslib/AltosFlashListener.java b/altoslib/AltosFlashListener.java index 8bb86bba..7a51c330 100644 --- a/altoslib/AltosFlashListener.java +++ b/altoslib/AltosFlashListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public interface AltosFlashListener { public void position(String label, int percent); diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java index 2fcd556e..be103838 100644 --- a/altoslib/AltosFlightReader.java +++ b/altoslib/AltosFlightReader.java @@ -15,22 +15,22 @@ * 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 { } @@ -38,12 +38,18 @@ public class AltosFlightReader { 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; } diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java index 56feb848..1b88cb9f 100644 --- a/altoslib/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java index 7c291ea9..6093df49 100644 --- a/altoslib/AltosFrequency.java +++ b/altoslib/AltosFrequency.java @@ -15,7 +15,7 @@ * 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; @@ -41,4 +41,4 @@ public class AltosFrequency { frequency = f; description = d; } -}
\ No newline at end of file +} diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index 2708d026..0154e95d 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.text.*; import java.util.concurrent.*; @@ -40,10 +40,11 @@ public class AltosGPS implements Cloneable { 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 */ @@ -95,6 +96,7 @@ public class AltosGPS implements Cloneable { 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); @@ -268,14 +270,26 @@ public class AltosGPS implements Cloneable { 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(); @@ -295,7 +309,9 @@ public class AltosGPS implements Cloneable { 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 */ @@ -327,9 +343,11 @@ public class AltosGPS implements Cloneable { 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]; @@ -340,11 +358,7 @@ public class AltosGPS implements Cloneable { } } } else { - lat = AltosLib.MISSING; - lon = AltosLib.MISSING; - alt = AltosLib.MISSING; - ClearGPSTime(); - cc_gps_sat = null; + init(); } } diff --git a/altoslib/AltosGPSSat.java b/altoslib/AltosGPSSat.java index ef24d497..adbcbe61 100644 --- a/altoslib/AltosGPSSat.java +++ b/altoslib/AltosGPSSat.java @@ -15,7 +15,7 @@ * 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; diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java index 4782c34d..716eeef9 100644 --- a/altoslib/AltosGreatCircle.java +++ b/altoslib/AltosGreatCircle.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.lang.Math; diff --git a/altoslib/AltosHeight.java b/altoslib/AltosHeight.java index 84981032..8c67e043 100644 --- a/altoslib/AltosHeight.java +++ b/altoslib/AltosHeight.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosHeight extends AltosUnits { diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java index d5fa8f5f..9ee64bdc 100644 --- a/altoslib/AltosHexfile.java +++ b/altoslib/AltosHexfile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.LinkedList; diff --git a/altoslib/AltosHexsym.java b/altoslib/AltosHexsym.java index 403b5644..52eb81db 100644 --- a/altoslib/AltosHexsym.java +++ b/altoslib/AltosHexsym.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosHexsym { String name; diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index a22b3fed..89d7def4 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.*; diff --git a/altoslib/AltosIdle.java b/altoslib/AltosIdle.java index 55f6f5c9..0f723d14 100644 --- a/altoslib/AltosIdle.java +++ b/altoslib/AltosIdle.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 5cd8bf36..50745d97 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -118,6 +118,10 @@ public class AltosIdleFetch implements AltosStateUpdate { 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; diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index f81abdff..85bcff10 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.concurrent.*; diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java index 6a9abea2..4382430c 100644 --- a/altoslib/AltosIdleMonitorListener.java +++ b/altoslib/AltosIdleMonitorListener.java @@ -15,7 +15,7 @@ * 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); diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java index c21f17ac..b458911e 100644 --- a/altoslib/AltosIgnite.java +++ b/altoslib/AltosIgnite.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.*; import java.io.*; diff --git a/altoslib/AltosKML.java b/altoslib/AltosKML.java index d55da9ef..e701fda3 100644 --- a/altoslib/AltosKML.java +++ b/altoslib/AltosKML.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; @@ -28,18 +28,25 @@ public class AltosKML implements AltosWriter { 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" + @@ -95,7 +102,8 @@ public class AltosKML implements AltosWriter { 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); diff --git a/altoslib/AltosLatitude.java b/altoslib/AltosLatitude.java index 6156d6dc..2b507173 100644 --- a/altoslib/AltosLatitude.java +++ b/altoslib/AltosLatitude.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosLatitude extends AltosLocation { public String pos() { return "N"; } diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 69c6d604..2e9dc648 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.*; import java.io.*; @@ -51,6 +51,20 @@ public class AltosLib { 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; @@ -98,6 +112,7 @@ public class AltosLib { 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; @@ -129,7 +144,8 @@ public class AltosLib { 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) { @@ -161,6 +177,15 @@ public class AltosLib { "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; @@ -206,6 +231,31 @@ public class AltosLib { 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", @@ -281,7 +331,7 @@ public class AltosLib { 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') @@ -291,7 +341,7 @@ public class AltosLib { 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; @@ -415,10 +465,17 @@ public class AltosLib { 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; } diff --git a/altoslib/AltosLine.java b/altoslib/AltosLine.java index f9c712a3..f56938c6 100644 --- a/altoslib/AltosLine.java +++ b/altoslib/AltosLine.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosLine { public String line; diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 7f434a06..62bd82b9 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.concurrent.*; @@ -163,8 +163,21 @@ public abstract class AltosLink implements Runnable { 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; @@ -274,6 +287,8 @@ public abstract class AltosLink implements Runnable { } public void flush_output() { + if (pending_output == null) + return; for (String s : pending_output) System.out.print(s); pending_output.clear(); @@ -305,6 +320,7 @@ public abstract class AltosLink implements Runnable { */ 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; @@ -356,6 +372,15 @@ public abstract class AltosLink implements Runnable { 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) @@ -383,10 +408,14 @@ public abstract class AltosLink implements Runnable { 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; } } @@ -430,7 +459,12 @@ public abstract class AltosLink implements Runnable { 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; diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java index 5bf761b0..054ff1d0 100644 --- a/altoslib/AltosListenerState.java +++ b/altoslib/AltosListenerState.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosListenerState { public int crc_errors; diff --git a/altoslib/AltosLocation.java b/altoslib/AltosLocation.java index 725a02ba..9bbbb899 100644 --- a/altoslib/AltosLocation.java +++ b/altoslib/AltosLocation.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public abstract class AltosLocation extends AltosUnits { diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java index c4e9e425..28116e3d 100644 --- a/altoslib/AltosLog.java +++ b/altoslib/AltosLog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.text.*; @@ -72,6 +72,7 @@ public class AltosLog implements Runnable { } log_file.flush(); file = a; + AltosPreferences.set_logfile(link.serial, file); } return log_file != null; } diff --git a/altoslib/AltosLongitude.java b/altoslib/AltosLongitude.java index 29a5dcd4..dbcd6bf0 100644 --- a/altoslib/AltosLongitude.java +++ b/altoslib/AltosLongitude.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosLongitude extends AltosLocation { public String pos() { return "E"; } diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index 9262de2d..690241f1 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.*; diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java index cb2e63d4..7f0dab98 100644 --- a/altoslib/AltosMma655x.java +++ b/altoslib/AltosMma655x.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.*; @@ -23,14 +23,15 @@ public class AltosMma655x implements Cloneable { 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() { @@ -51,17 +52,18 @@ public class AltosMma655x implements Cloneable { 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; } } diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index 5aa3a7ec..81e0641c 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.*; diff --git a/altoslib/AltosNoSymbol.java b/altoslib/AltosNoSymbol.java index f5e53b8c..d436c3f1 100644 --- a/altoslib/AltosNoSymbol.java +++ b/altoslib/AltosNoSymbol.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosNoSymbol extends Exception { public AltosNoSymbol(String name) { diff --git a/altoslib/AltosOrient.java b/altoslib/AltosOrient.java index 5fcbe28d..348c6844 100644 --- a/altoslib/AltosOrient.java +++ b/altoslib/AltosOrient.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosOrient extends AltosUnits { diff --git a/altoslib/AltosParse.java b/altoslib/AltosParse.java index 1bff7682..9cb99a0d 100644 --- a/altoslib/AltosParse.java +++ b/altoslib/AltosParse.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.text.*; diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index d299f27b..dba57dcb 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -35,6 +35,12 @@ public class AltosPreferences { /* 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"; @@ -50,6 +56,9 @@ public class AltosPreferences { /* 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"; @@ -74,6 +83,12 @@ public class AltosPreferences { /* 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; @@ -86,6 +101,8 @@ public class AltosPreferences { /* 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; @@ -140,6 +157,10 @@ public class AltosPreferences { public static int launcher_channel; public static void init(AltosPreferencesBackend in_backend) { + + if (backend != null) + return; + backend = in_backend; /* Initialize logdir from preferences */ @@ -159,12 +180,18 @@ public class AltosPreferences { 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); @@ -266,6 +293,46 @@ public class AltosPreferences { } } + 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; @@ -280,6 +347,20 @@ public class AltosPreferences { } } + 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; diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java index 461b5c80..76a99acb 100644 --- a/altoslib/AltosPreferencesBackend.java +++ b/altoslib/AltosPreferencesBackend.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.File; diff --git a/altoslib/AltosProgrammer.java b/altoslib/AltosProgrammer.java index c96f04ca..443082d5 100644 --- a/altoslib/AltosProgrammer.java +++ b/altoslib/AltosProgrammer.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java index 9e47bc80..60b8fe52 100644 --- a/altoslib/AltosPyro.java +++ b/altoslib/AltosPyro.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.*; import java.text.*; diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java index bf7e0e5b..2864e02a 100644 --- a/altoslib/AltosReplayReader.java +++ b/altoslib/AltosReplayReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -27,6 +27,7 @@ import java.util.*; public class AltosReplayReader extends AltosFlightReader { Iterator<AltosState> iterator; File file; + boolean real_time; public AltosState read() { if (iterator.hasNext()) @@ -39,16 +40,22 @@ public class AltosReplayReader extends AltosFlightReader { 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); + } } diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java index 10df11af..d0de5492 100644 --- a/altoslib/AltosRomconfig.java +++ b/altoslib/AltosRomconfig.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java index 502c6d65..3ec69213 100644 --- a/altoslib/AltosSelfFlash.java +++ b/altoslib/AltosSelfFlash.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; diff --git a/altoslib/AltosSensorEMini.java b/altoslib/AltosSensorEMini.java index ee0238f9..53a8e998 100644 --- a/altoslib/AltosSensorEMini.java +++ b/altoslib/AltosSensorEMini.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java index e34e71b7..cdc2ac42 100644 --- a/altoslib/AltosSensorMM.java +++ b/altoslib/AltosSensorMM.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorMega.java b/altoslib/AltosSensorMega.java index 02f3a256..3c7213eb 100644 --- a/altoslib/AltosSensorMega.java +++ b/altoslib/AltosSensorMega.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorMetrum.java b/altoslib/AltosSensorMetrum.java index e5421ef5..d977e886 100644 --- a/altoslib/AltosSensorMetrum.java +++ b/altoslib/AltosSensorMetrum.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index 2d60d8cf..344e7449 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorTMini.java b/altoslib/AltosSensorTMini.java index b9eeca0c..edd76da2 100644 --- a/altoslib/AltosSensorTMini.java +++ b/altoslib/AltosSensorTMini.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java index 9134f5f4..d2f86214 100644 --- a/altoslib/AltosSpeed.java +++ b/altoslib/AltosSpeed.java @@ -15,7 +15,7 @@ * 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 { diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index b05cd358..5fce15c4 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -19,7 +19,7 @@ * Track flight state from telemetry or eeprom data stream */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosState implements Cloneable { @@ -271,6 +271,7 @@ 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? */ @@ -472,15 +473,23 @@ public class AltosState implements Cloneable { 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(); } @@ -762,6 +771,7 @@ public class AltosState implements Cloneable { product = null; serial = AltosLib.MISSING; receiver_serial = AltosLib.MISSING; + altitude_32 = AltosLib.MISSING; baro = null; companion = null; @@ -899,6 +909,7 @@ public class AltosState implements Cloneable { product = old.product; serial = old.serial; receiver_serial = old.receiver_serial; + altitude_32 = old.altitude_32; baro = old.baro; companion = old.companion; @@ -1024,15 +1035,27 @@ public class AltosState implements Cloneable { 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; } @@ -1043,9 +1066,7 @@ public class AltosState implements Cloneable { 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; } @@ -1056,6 +1077,15 @@ public class AltosState implements Cloneable { 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; diff --git a/altoslib/AltosStateIterable.java b/altoslib/AltosStateIterable.java index be812095..4154b71c 100644 --- a/altoslib/AltosStateIterable.java +++ b/altoslib/AltosStateIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; @@ -26,4 +26,18 @@ public abstract class AltosStateIterable implements Iterable<AltosState> { } 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); + } } diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosStateUpdate.java index ac4e963e..70530f75 100644 --- a/altoslib/AltosStateUpdate.java +++ b/altoslib/AltosStateUpdate.java @@ -15,7 +15,7 @@ * 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; diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index 8182ec6b..a123d752 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.text.*; @@ -114,6 +114,29 @@ public abstract class AltosTelemetry implements AltosStateUpdate { 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; diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java index e3884051..f578e6ad 100644 --- a/altoslib/AltosTelemetryConfiguration.java +++ b/altoslib/AltosTelemetryConfiguration.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetryConfiguration extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index 3d3fa407..15344b8d 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java index cba97ddc..ac42597d 100644 --- a/altoslib/AltosTelemetryIterable.java +++ b/altoslib/AltosTelemetryIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.io.*; import java.util.*; diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java index 3367ece7..72a8bc4a 100644 --- a/altoslib/AltosTelemetryLegacy.java +++ b/altoslib/AltosTelemetryLegacy.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.text.*; @@ -186,6 +186,7 @@ public class AltosTelemetryLegacy extends AltosTelemetry { * 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) @@ -209,6 +210,7 @@ public class AltosTelemetryLegacy extends AltosTelemetry { 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"; diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java index 8368188f..427ae16e 100644 --- a/altoslib/AltosTelemetryLocation.java +++ b/altoslib/AltosTelemetryLocation.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetryLocation extends AltosTelemetryStandard { @@ -37,11 +37,12 @@ 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); @@ -57,6 +58,11 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard { 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) { @@ -80,8 +86,9 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard { 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(); } diff --git a/altoslib/AltosTelemetryMap.java b/altoslib/AltosTelemetryMap.java index 8d0de355..758311eb 100644 --- a/altoslib/AltosTelemetryMap.java +++ b/altoslib/AltosTelemetryMap.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.text.*; import java.util.HashMap; diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java index fac5695f..d949c02f 100644 --- a/altoslib/AltosTelemetryMegaData.java +++ b/altoslib/AltosTelemetryMegaData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetryMegaData extends AltosTelemetryStandard { int state; @@ -31,12 +31,12 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard { 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); @@ -44,7 +44,7 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard { 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; } @@ -55,7 +55,8 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard { acceleration = int16(26); speed = int16(28); - height = int16(30); + + height_16 = int16(30); } public void update_state(AltosState state) { @@ -79,7 +80,13 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard { 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); } } diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java index 9e73bc4e..1b568c88 100644 --- a/altoslib/AltosTelemetryMegaSensor.java +++ b/altoslib/AltosTelemetryMegaSensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetryMegaSensor extends AltosTelemetryStandard { int accel; diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java index 96617306..3377d969 100644 --- a/altoslib/AltosTelemetryMetrumData.java +++ b/altoslib/AltosTelemetryMetrumData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetryMetrumData extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java index e7055404..beab6da9 100644 --- a/altoslib/AltosTelemetryMetrumSensor.java +++ b/altoslib/AltosTelemetryMetrumSensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { @@ -27,7 +27,7 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { int acceleration; int speed; - int height; + int height_16; int v_batt; int sense_a; @@ -43,7 +43,7 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { acceleration = int16(14); speed = int16(16); - height = int16(18); + height_16 = int16(18); v_batt = int16(20); sense_a = int16(22); @@ -59,7 +59,8 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { 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)); diff --git a/altoslib/AltosTelemetryMini.java b/altoslib/AltosTelemetryMini.java index fbfaff8e..221bb67c 100644 --- a/altoslib/AltosTelemetryMini.java +++ b/altoslib/AltosTelemetryMini.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetryMini extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java index 0dca62aa..2a535e84 100644 --- a/altoslib/AltosTelemetryRaw.java +++ b/altoslib/AltosTelemetryRaw.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetryRaw extends AltosTelemetryStandard { public AltosTelemetryRaw(int[] bytes) { diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 3dff661a..7539452d 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; import java.text.*; import java.io.*; @@ -26,11 +26,19 @@ public class AltosTelemetryReader extends AltosFlightReader { 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"); @@ -52,6 +60,12 @@ public class AltosTelemetryReader extends AltosFlightReader { } public void close(boolean interrupted) { + + if (stacked != null) { + stacked.close(interrupted); + stacked = null; + } + link.remove_monitor(telem); log.close(); try { @@ -92,6 +106,23 @@ public class AltosTelemetryReader extends AltosFlightReader { } } + 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); } @@ -105,6 +136,15 @@ public class AltosTelemetryReader extends AltosFlightReader { 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); } @@ -121,9 +161,10 @@ public class AltosTelemetryReader extends AltosFlightReader { 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); @@ -133,6 +174,8 @@ public class AltosTelemetryReader extends AltosFlightReader { 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 { @@ -140,4 +183,22 @@ public class AltosTelemetryReader extends AltosFlightReader { close(true); } } + + private static AltosFlightReader existing_data(AltosLink link) { + if (link == null) + return null; + + File file = AltosPreferences.logfile(link.serial); + if (file != null) { + AltosStateIterable iterable = AltosStateIterable.iterable(file); + if (iterable != null) + return new AltosReplayReader(iterable.iterator(), file, false); + } + return null; + } + + public AltosTelemetryReader(AltosLink link) + throws IOException, InterruptedException, TimeoutException { + this(link, existing_data(link)); + } } diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java index d611e88c..d1cdaf6d 100644 --- a/altoslib/AltosTelemetrySatellite.java +++ b/altoslib/AltosTelemetrySatellite.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetrySatellite extends AltosTelemetryStandard { int channels; diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java index ad4d9283..fc3fe858 100644 --- a/altoslib/AltosTelemetrySensor.java +++ b/altoslib/AltosTelemetrySensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTelemetrySensor extends AltosTelemetryStandard { diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java index 23ae9d21..f4dfd8e9 100644 --- a/altoslib/AltosTelemetryStandard.java +++ b/altoslib/AltosTelemetryStandard.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public abstract class AltosTelemetryStandard extends AltosTelemetry { int[] bytes; diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java index 5fa71b86..e654fada 100644 --- a/altoslib/AltosTemperature.java +++ b/altoslib/AltosTemperature.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosTemperature extends AltosUnits { diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java index d29cfae7..dbdb7882 100644 --- a/altoslib/AltosUnits.java +++ b/altoslib/AltosUnits.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public abstract class AltosUnits { diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java index ca6faafd..664aed67 100644 --- a/altoslib/AltosUnitsListener.java +++ b/altoslib/AltosUnitsListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public interface AltosUnitsListener { public void units_changed(boolean imperial_units); diff --git a/altoslib/AltosVoltage.java b/altoslib/AltosVoltage.java index 351bf115..22bd1aee 100644 --- a/altoslib/AltosVoltage.java +++ b/altoslib/AltosVoltage.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_4; +package org.altusmetrum.altoslib_5; public class AltosVoltage extends AltosUnits { diff --git a/altoslib/AltosWriter.java b/altoslib/AltosWriter.java index c3479a93..fb208b02 100644 --- a/altoslib/AltosWriter.java +++ b/altoslib/AltosWriter.java @@ -15,12 +15,10 @@ * 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(); diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index e81418bb..0ad9b7da 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -131,7 +131,7 @@ JAR=altoslib_$(ALTOSLIB_VERSION).jar all-local: $(JAR) clean-local: - -rm -rf bin $(JAR) + -rm -rf $(JAVAROOT) altoslib_*.jar install-altoslibJAVA: $(JAR) @$(NORMAL_INSTALL) diff --git a/altosui/.gitignore b/altosui/.gitignore index 10b600e4..a9b80aa4 100644 --- a/altosui/.gitignore +++ b/altosui/.gitignore @@ -17,7 +17,7 @@ Altos-Linux-*.tar.bz2 Altos-Linux-*.sh Altos-Mac-*.zip Altos-Windows-*.exe -altos.desktop +.desktop *.dll *.dylib *.so diff --git a/altosui/Altos.java b/altosui/Altos.java index 28038ad6..74b45f1c 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -20,8 +20,8 @@ package altosui; 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 { diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index 3bc80406..24fc362f 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -21,8 +21,8 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class AltosAscent extends AltosUIFlightTab { JLabel cur, max; diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index e7b335ac..7ac53dd8 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -19,8 +19,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_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; diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 6eb7d40c..40f7ebec 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -22,8 +22,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.text.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class AltosConfig implements ActionListener { diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java index f0b4f0f9..64336c8e 100644 --- a/altosui/AltosConfigPyroUI.java +++ b/altosui/AltosConfigPyroUI.java @@ -21,8 +21,8 @@ import java.awt.*; 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 @@ -285,9 +285,13 @@ public class AltosConfigPyroUI "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 { @@ -301,23 +305,28 @@ public class AltosConfigPyroUI } 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) { diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java index bfbd2c77..9020ed9d 100644 --- a/altosui/AltosConfigTD.java +++ b/altosui/AltosConfigTD.java @@ -21,8 +21,8 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class AltosConfigTD implements ActionListener { @@ -62,6 +62,7 @@ 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; @@ -105,6 +106,7 @@ public class AltosConfigTD implements ActionListener { 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; @@ -140,6 +142,7 @@ public class AltosConfigTD implements ActionListener { 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); } @@ -151,6 +154,7 @@ public class AltosConfigTD implements ActionListener { 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"); @@ -178,6 +182,17 @@ public class AltosConfigTD implements ActionListener { } } + 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; @@ -208,8 +223,10 @@ public class AltosConfigTD implements ActionListener { 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) { } @@ -218,6 +235,7 @@ public class AltosConfigTD implements ActionListener { * 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"); } @@ -226,6 +244,8 @@ public class AltosConfigTD implements ActionListener { if (frequency != 0) AltosPreferences.set_frequency(serial.get(), frequency); + AltosPreferences.set_telemetry_rate(serial.get(), + telemetry_rate()); } public void run () { @@ -259,8 +279,10 @@ public class AltosConfigTD implements ActionListener { } 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()), @@ -279,6 +301,8 @@ public class AltosConfigTD implements ActionListener { 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); } @@ -311,6 +335,7 @@ public class AltosConfigTD implements ActionListener { 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"); @@ -340,4 +365,4 @@ public class AltosConfigTD implements ActionListener { } } } -}
\ No newline at end of file +} diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java index 22b3384d..b677ad23 100644 --- a/altosui/AltosConfigTDUI.java +++ b/altosui/AltosConfigTDUI.java @@ -21,8 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class AltosConfigTDUI extends AltosUIDialog @@ -37,6 +37,7 @@ public class AltosConfigTDUI JLabel frequency_label; JLabel radio_calibration_label; JLabel radio_frequency_label; + JLabel rate_label; public boolean dirty; @@ -44,8 +45,9 @@ public class AltosConfigTDUI 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; @@ -54,7 +56,6 @@ public class AltosConfigTDUI ActionListener listener; - /* A window listener to catch closing events and tell the config code */ class ConfigListener extends WindowAdapter { AltosConfigTDUI ui; @@ -166,7 +167,7 @@ public class AltosConfigTDUI 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"); @@ -193,6 +194,28 @@ public class AltosConfigTDUI 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; @@ -340,6 +363,14 @@ public class AltosConfigTDUI 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; } diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 1b5ff988..9fcace61 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -21,8 +21,8 @@ import java.awt.*; 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 @@ -40,7 +40,9 @@ public class AltosConfigUI 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; @@ -58,10 +60,12 @@ public class AltosConfigUI 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; @@ -113,6 +117,10 @@ public class AltosConfigUI "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", @@ -194,6 +202,13 @@ public class AltosConfigUI 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"); @@ -201,6 +216,15 @@ public class AltosConfigUI 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)"); @@ -417,7 +441,7 @@ public class AltosConfigUI 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"); @@ -475,6 +499,31 @@ public class AltosConfigUI 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; @@ -501,6 +550,33 @@ public class AltosConfigUI 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; @@ -850,9 +926,16 @@ public class AltosConfigUI 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() { @@ -880,6 +963,8 @@ public class AltosConfigUI } 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(); @@ -892,9 +977,15 @@ public class AltosConfigUI 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); } @@ -917,6 +1008,9 @@ public class AltosConfigUI 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 { @@ -924,6 +1018,7 @@ public class AltosConfigUI } 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); } @@ -933,6 +1028,8 @@ public class AltosConfigUI 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 @@ -944,12 +1041,14 @@ public class AltosConfigUI } 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(); @@ -962,8 +1061,20 @@ public class AltosConfigUI 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); } @@ -985,6 +1096,9 @@ public class AltosConfigUI } 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(); @@ -1011,6 +1125,9 @@ public class AltosConfigUI } 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) { @@ -1032,14 +1149,13 @@ public class AltosConfigUI 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(); } @@ -1052,6 +1168,9 @@ public class AltosConfigUI } 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]))) { @@ -1103,12 +1222,13 @@ public class AltosConfigUI } 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)); } } @@ -1118,12 +1238,13 @@ public class AltosConfigUI } 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)); } } @@ -1159,6 +1280,9 @@ public class AltosConfigUI } 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) @@ -1166,7 +1290,6 @@ public class AltosConfigUI 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(); } @@ -1177,4 +1300,17 @@ public class AltosConfigUI 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; + } } diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index e61a4a5b..85a3f6c0 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -22,7 +22,7 @@ import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; public class AltosConfigureUI extends AltosUIConfigure @@ -89,6 +89,8 @@ public class AltosConfigureUI row++; } + boolean has_bluetooth; + public void add_bluetooth() { JButton manage_bluetooth = new JButton("Manage Bluetooth"); manage_bluetooth.addActionListener(new ActionListener() { @@ -98,6 +100,7 @@ public class AltosConfigureUI }); 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() { @@ -108,7 +111,10 @@ public class AltosConfigureUI } }); 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++; } diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 36fc1613..e38b35ed 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -21,8 +21,8 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class AltosDescent extends AltosUIFlightTab { diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 46c0b387..7e7efa64 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -19,8 +19,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_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; diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java index b33f40a4..336b44aa 100644 --- a/altosui/AltosFlightStatusTableModel.java +++ b/altosui/AltosFlightStatusTableModel.java @@ -27,7 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosFlightStatusTableModel extends AbstractTableModel { private String[] columnNames = { diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java index 0daec04e..3ba78c19 100644 --- a/altosui/AltosFlightStatusUpdate.java +++ b/altosui/AltosFlightStatusUpdate.java @@ -18,7 +18,7 @@ package altosui; import java.awt.event.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosFlightStatusUpdate implements ActionListener { diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 43deb631..6af345ea 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -22,8 +22,8 @@ import java.awt.event.*; import javax.swing.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_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; @@ -169,10 +169,11 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { 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; @@ -193,8 +194,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { /* 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() { @@ -217,27 +218,40 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { 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; @@ -256,7 +270,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { version = "Telemetry: None"; telemetry = new JLabel(version); - c.gridx = 1; + c.gridx = 2; c.gridy = 0; c.weightx = 0; c.weighty = 0; @@ -274,9 +288,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { 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 @@ -315,7 +328,6 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { c.fill = GridBagConstraints.BOTH; c.weightx = 1; c.weighty = 1; - c.gridwidth = 2; bag.add(pane, c); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 07fe9317..ddd281a6 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -23,8 +23,8 @@ import java.util.ArrayList; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_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; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 042111ec..67b7a989 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -24,8 +24,8 @@ import javax.swing.event.*; import java.io.*; import java.util.concurrent.*; import java.util.Arrays; -import org.altusmetrum.altoslib_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; @@ -33,9 +33,11 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl AltosPad pad; AltosInfoTable flightInfo; AltosFlightStatus flightStatus; + AltosIgnitor ignitor; AltosIdleMonitor thread; int serial; boolean remote; + boolean has_ignitor; void stop_display() { if (thread != null) { @@ -70,10 +72,22 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl 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); // } @@ -89,7 +103,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl } Container bag; - AltosFreqList frequencies; + AltosUIFreqList frequencies; JTextField callsign_value; /* DocumentListener interface methods */ @@ -186,7 +200,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl /* 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(); @@ -222,6 +236,8 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl 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)); diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index c251bbe2..15a81e57 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -24,8 +24,8 @@ import java.io.*; import java.text.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class AltosIgniteUI extends AltosUIDialog diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java index 990a87e6..117def09 100644 --- a/altosui/AltosIgnitor.java +++ b/altosui/AltosIgnitor.java @@ -20,8 +20,8 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class AltosIgnitor extends AltosUIFlightTab { diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index dd5cf9ab..7c50adac 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -21,8 +21,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class AltosLanded extends AltosUIFlightTab implements ActionListener { @@ -151,6 +151,12 @@ 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; diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java index 9ac1e44c..17178616 100644 --- a/altosui/AltosLaunch.java +++ b/altosui/AltosLaunch.java @@ -20,7 +20,7 @@ package altosui; import java.io.*; import java.util.concurrent.*; import java.awt.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; public class AltosLaunch { AltosDevice device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index cc082542..3320e675 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -23,7 +23,7 @@ import javax.swing.*; import java.io.*; import java.text.*; import java.util.concurrent.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; class FireButton extends JButton { protected void processMouseEvent(MouseEvent e) { diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 6b5fd150..eb0c5644 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -18,8 +18,8 @@ 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 { @@ -117,6 +117,17 @@ 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; @@ -126,12 +137,12 @@ public class AltosPad extends AltosUIFlightTab { 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) { @@ -163,12 +174,12 @@ public class AltosPad extends AltosUIFlightTab { 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) { @@ -200,12 +211,12 @@ public class AltosPad extends AltosUIFlightTab { 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) { diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 6137487c..0aa5d03c 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -22,8 +22,8 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_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(); @@ -99,10 +99,25 @@ public class AltosUI extends AltosUIFrame { 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(); diff --git a/altosui/AltosUIPreferencesBackend.java b/altosui/AltosUIPreferencesBackend.java index 28047086..b229d7b2 100644 --- a/altosui/AltosUIPreferencesBackend.java +++ b/altosui/AltosUIPreferencesBackend.java @@ -19,7 +19,7 @@ package altosui; 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 { diff --git a/altosui/Info.plist.in b/altosui/Info.plist.in index 46dea171..8dc797d6 100644 --- a/altosui/Info.plist.in +++ b/altosui/Info.plist.in @@ -23,7 +23,34 @@ <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> diff --git a/altosui/Instdrv/NSIS/Includes/java.nsh b/altosui/Instdrv/NSIS/Includes/java.nsh index ebf1c5b9..cd47c1b5 100644 --- a/altosui/Instdrv/NSIS/Includes/java.nsh +++ b/altosui/Instdrv/NSIS/Includes/java.nsh @@ -32,19 +32,135 @@ Function GetJRE 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 diff --git a/altosui/Instdrv/NSIS/Includes/refresh-sh.nsh b/altosui/Instdrv/NSIS/Includes/refresh-sh.nsh new file mode 100644 index 00000000..23d8e5e4 --- /dev/null +++ b/altosui/Instdrv/NSIS/Includes/refresh-sh.nsh @@ -0,0 +1,14 @@ +!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 diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 4cb5df58..48f58933 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -64,7 +64,7 @@ LIBALTOS= \ altos.dll desktopdir = $(datadir)/applications -desktop_file = altos.desktop +desktop_file = altusmetrum-altosui.desktop desktop_SCRIPTS = $(desktop_file) JAR=altosui.jar @@ -72,26 +72,45 @@ 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 @@ -115,10 +134,13 @@ FIRMWARE_TMEGA=$(FIRMWARE_TMEGA_1_0) 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 @@ -141,14 +163,14 @@ FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFR 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 @@ -156,12 +178,12 @@ clean-local: -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 @@ -195,7 +217,6 @@ else fat: $(LINUX_DIST) $(LINUX_SH) $(MACOSX_DIST) $(WINDOWS_DIST) endif - altosuidir=$(datadir)/java install-altosuiJAVA: altosui.jar @@ -325,7 +346,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile 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 @@ -336,6 +357,6 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile 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) diff --git a/altosui/altos-windows.nsi.in b/altosui/altos-windows.nsi.in index 2e2a46f1..11c1dc07 100644 --- a/altosui/altos-windows.nsi.in +++ b/altosui/altos-windows.nsi.in @@ -2,16 +2,24 @@ !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" @@ -21,7 +29,7 @@ RequestExecutionLevel admin ShowInstDetails Show -ComponentText "Altus Metrum Software and Driver Installer" +ComponentText "${REG_NAME} Software and Driver Installer" Function .onInit DetailPrint "Checking host operating system" @@ -33,6 +41,16 @@ Function .onInit ${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 @@ -68,12 +86,12 @@ done: 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" @@ -88,16 +106,16 @@ Section "AltosUI Application" 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 @@ -111,6 +129,7 @@ Section "TeleMetrum, TeleDongle and TeleBT Firmware" 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 @@ -127,38 +146,105 @@ Section "Documentation" 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 diff --git a/altosui/altos.desktop.in b/altosui/altusmetrum-altosui.desktop.in index 66114348..10fd9e9d 100644 --- a/altosui/altos.desktop.in +++ b/altosui/altusmetrum-altosui.desktop.in @@ -1,10 +1,11 @@ [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.svg +Icon=%icondir%/altusmetrum-altosui.svg Exec=%bindir%/altosui %f Terminal=false -MimeType=text/plain; +MimeType=application/vnd.altusmetrum.telemetry;application/vnd.altusmetrum.eeprom Categories=Education;Electronics;Science; diff --git a/altosui/linux-install.sh b/altosui/linux-install.sh index 957b1aad..2e44c2aa 100644 --- a/altosui/linux-install.sh +++ b/altosui/linux-install.sh @@ -130,6 +130,7 @@ esac # # Create the .desktop file by editing the paths # + case "$target" in /*) target_abs="$target" @@ -149,43 +150,46 @@ for infile in "$target"/AltOS/*.desktop.in; do 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 @@ -222,13 +226,14 @@ if [ -d $HOME/Desktop ]; then 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." diff --git a/altosuilib/AltosBTDevice.java b/altosuilib/AltosBTDevice.java index beefa532..2c085021 100644 --- a/altosuilib/AltosBTDevice.java +++ b/altosuilib/AltosBTDevice.java @@ -15,10 +15,10 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 { diff --git a/altosuilib/AltosBTDeviceIterator.java b/altosuilib/AltosBTDeviceIterator.java index cad60ffb..c99b27f9 100644 --- a/altosuilib/AltosBTDeviceIterator.java +++ b/altosuilib/AltosBTDeviceIterator.java @@ -15,11 +15,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosBTKnown.java b/altosuilib/AltosBTKnown.java index 02883c75..c526269d 100644 --- a/altosuilib/AltosBTKnown.java +++ b/altosuilib/AltosBTKnown.java @@ -15,10 +15,10 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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>(); diff --git a/altosuilib/AltosBTManage.java b/altosuilib/AltosBTManage.java index 6da0a3eb..b953ca92 100644 --- a/altosuilib/AltosBTManage.java +++ b/altosuilib/AltosBTManage.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import java.awt.event.*; @@ -23,7 +23,7 @@ import javax.swing.*; import javax.swing.plaf.basic.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> { LinkedBlockingQueue<AltosBTDevice> found_devices; diff --git a/altosuilib/AltosCSVUI.java b/altosuilib/AltosCSVUI.java index 0a5e4fa2..6328d37d 100644 --- a/altosuilib/AltosCSVUI.java +++ b/altosuilib/AltosCSVUI.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 diff --git a/altosuilib/AltosConfigFreqUI.java b/altosuilib/AltosConfigFreqUI.java index 6dcd63b8..a0525a00 100644 --- a/altosuilib/AltosConfigFreqUI.java +++ b/altosuilib/AltosConfigFreqUI.java @@ -15,13 +15,13 @@ * 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; diff --git a/altosuilib/AltosDataChooser.java b/altosuilib/AltosDataChooser.java index 59891c4a..1990faf1 100644 --- a/altosuilib/AltosDataChooser.java +++ b/altosuilib/AltosDataChooser.java @@ -15,12 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosDevice.java b/altosuilib/AltosDevice.java index 251ae994..1f5536ff 100644 --- a/altosuilib/AltosDevice.java +++ b/altosuilib/AltosDevice.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import libaltosJNI.*; diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java index 0bedea97..d2ccd5e7 100644 --- a/altosuilib/AltosDeviceDialog.java +++ b/altosuilib/AltosDeviceDialog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import javax.swing.*; import java.awt.*; @@ -131,7 +131,8 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL buttonPane.add(cancel_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - add_bluetooth(); + if (AltosUILib.has_bluetooth) + add_bluetooth(); buttonPane.add(select_button); diff --git a/altosuilib/AltosDeviceUIDialog.java b/altosuilib/AltosDeviceUIDialog.java index 3013612a..80a76d6d 100644 --- a/altosuilib/AltosDeviceUIDialog.java +++ b/altosuilib/AltosDeviceUIDialog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import javax.swing.*; import java.awt.*; diff --git a/altosuilib/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java index 06bc68a9..6b6e03e7 100644 --- a/altosuilib/AltosDisplayThread.java +++ b/altosuilib/AltosDisplayThread.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 { diff --git a/altosuilib/AltosEepromDelete.java b/altosuilib/AltosEepromDelete.java index 981daddf..39585dad 100644 --- a/altosuilib/AltosEepromDelete.java +++ b/altosuilib/AltosEepromDelete.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosEepromManage.java b/altosuilib/AltosEepromManage.java index 2b967339..81dd3d13 100644 --- a/altosuilib/AltosEepromManage.java +++ b/altosuilib/AltosEepromManage.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 { diff --git a/altosuilib/AltosEepromMonitor.java b/altosuilib/AltosEepromMonitor.java index b1e85622..060d0474 100644 --- a/altosuilib/AltosEepromMonitor.java +++ b/altosuilib/AltosEepromMonitor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/AltosEepromMonitorUI.java b/altosuilib/AltosEepromMonitorUI.java index 02c71cd9..11dd4adb 100644 --- a/altosuilib/AltosEepromMonitorUI.java +++ b/altosuilib/AltosEepromMonitorUI.java @@ -15,12 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosEepromSelect.java b/altosuilib/AltosEepromSelect.java index 293d3045..1adfdab5 100644 --- a/altosuilib/AltosEepromSelect.java +++ b/altosuilib/AltosEepromSelect.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java index 3f120617..44be2a90 100644 --- a/altosuilib/AltosFlashUI.java +++ b/altosuilib/AltosFlashUI.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import java.awt.event.*; @@ -23,7 +23,7 @@ import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosFlashUI extends AltosUIDialog @@ -213,6 +213,7 @@ public class AltosFlashUI 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() { diff --git a/altosuilib/AltosFlightDisplay.java b/altosuilib/AltosFlightDisplay.java index 55b74034..d0f20bb4 100644 --- a/altosuilib/AltosFlightDisplay.java +++ b/altosuilib/AltosFlightDisplay.java @@ -15,9 +15,9 @@ * 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(); diff --git a/altosuilib/AltosFlightInfoTableModel.java b/altosuilib/AltosFlightInfoTableModel.java index 3995efb3..0bc4f847 100644 --- a/altosuilib/AltosFlightInfoTableModel.java +++ b/altosuilib/AltosFlightInfoTableModel.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import javax.swing.table.*; diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java index 703dfb9d..1ec4a03e 100644 --- a/altosuilib/AltosFlightStatsTable.java +++ b/altosuilib/AltosFlightStatsTable.java @@ -15,12 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosFontListener.java b/altosuilib/AltosFontListener.java index a98cc131..a1b2170b 100644 --- a/altosuilib/AltosFontListener.java +++ b/altosuilib/AltosFontListener.java @@ -15,7 +15,7 @@ * 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); diff --git a/altosuilib/AltosGraph.java b/altosuilib/AltosGraph.java index f8c8b27b..522eea1e 100644 --- a/altosuilib/AltosGraph.java +++ b/altosuilib/AltosGraph.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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.*; @@ -172,6 +172,29 @@ class AltosMagUnits extends AltosUnits { } } +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); @@ -191,6 +214,9 @@ public class AltosGraph extends AltosUIGraph { 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); @@ -212,11 +238,12 @@ public class AltosGraph extends AltosUIGraph { 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); @@ -236,6 +263,7 @@ public class AltosGraph extends AltosUIGraph { 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); @@ -325,6 +353,24 @@ public class AltosGraph extends AltosUIGraph { 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", diff --git a/altosuilib/AltosGraphDataPoint.java b/altosuilib/AltosGraphDataPoint.java index 3aff1e82..56dadb8b 100644 --- a/altosuilib/AltosGraphDataPoint.java +++ b/altosuilib/AltosGraphDataPoint.java @@ -15,9 +15,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosGraphDataPoint implements AltosUIDataPoint { @@ -53,7 +53,10 @@ 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; @@ -194,6 +197,24 @@ public class AltosGraphDataPoint implements AltosUIDataPoint { 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; diff --git a/altosuilib/AltosGraphDataSet.java b/altosuilib/AltosGraphDataSet.java index 36933e9b..0845f20e 100644 --- a/altosuilib/AltosGraphDataSet.java +++ b/altosuilib/AltosGraphDataSet.java @@ -15,12 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java index 23ae4ae5..625fe76f 100644 --- a/altosuilib/AltosInfoTable.java +++ b/altosuilib/AltosInfoTable.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; @@ -198,24 +198,28 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar 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)); @@ -234,12 +238,12 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar 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); diff --git a/altosuilib/AltosLed.java b/altosuilib/AltosLed.java index 2debb62a..0dd5740c 100644 --- a/altosuilib/AltosLed.java +++ b/altosuilib/AltosLed.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import javax.swing.*; diff --git a/altosuilib/AltosLights.java b/altosuilib/AltosLights.java index c91b70e9..30934d96 100644 --- a/altosuilib/AltosLights.java +++ b/altosuilib/AltosLights.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import javax.swing.*; diff --git a/altosuilib/AltosPositionListener.java b/altosuilib/AltosPositionListener.java index 34cf1650..dfc3c649 100644 --- a/altosuilib/AltosPositionListener.java +++ b/altosuilib/AltosPositionListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; public interface AltosPositionListener { public void position_changed(int position); diff --git a/altosuilib/AltosRomconfigUI.java b/altosuilib/AltosRomconfigUI.java index 8f002c4a..481ce656 100644 --- a/altosuilib/AltosRomconfigUI.java +++ b/altosuilib/AltosRomconfigUI.java @@ -15,12 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 diff --git a/altosuilib/AltosScanUI.java b/altosuilib/AltosScanUI.java index b0cde059..7e51a55a 100644 --- a/altosuilib/AltosScanUI.java +++ b/altosuilib/AltosScanUI.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import java.awt.event.*; @@ -25,7 +25,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; class AltosScanResult { String callsign; @@ -33,32 +33,40 @@ class AltosScanResult { 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) { @@ -132,15 +140,20 @@ public class AltosScanUI 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; @@ -189,10 +202,11 @@ public class AltosScanUI 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); @@ -217,12 +231,18 @@ public class AltosScanUI 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(); @@ -230,24 +250,43 @@ public class AltosScanUI void next() throws InterruptedException, TimeoutException { reader.set_monitor(false); + + /* Let any pending input from the last configuration drain out */ Thread.sleep(100); - ++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); @@ -297,15 +336,33 @@ public class AltosScanUI 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); } } @@ -341,6 +398,7 @@ public class AltosScanUI reader = new AltosTelemetryReader(new AltosSerial(device)); set_frequency(); set_telemetry(); + set_rate(); try { Thread.sleep(100); } catch (InterruptedException ie) { @@ -386,11 +444,13 @@ public class AltosScanUI 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; @@ -412,18 +472,24 @@ public class AltosScanUI 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; @@ -433,10 +499,35 @@ public class AltosScanUI 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(); @@ -444,15 +535,17 @@ public class AltosScanUI 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 diff --git a/altosuilib/AltosSerial.java b/altosuilib/AltosSerial.java index 60e15bdb..0eba55fd 100644 --- a/altosuilib/AltosSerial.java +++ b/altosuilib/AltosSerial.java @@ -19,13 +19,13 @@ * 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.*; /* diff --git a/altosuilib/AltosSerialInUseException.java b/altosuilib/AltosSerialInUseException.java index 1e8207d1..cd19b101 100644 --- a/altosuilib/AltosSerialInUseException.java +++ b/altosuilib/AltosSerialInUseException.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; public class AltosSerialInUseException extends Exception { public AltosDevice device; diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java index 74561673..9e98ddb7 100644 --- a/altosuilib/AltosUIAxis.java +++ b/altosuilib/AltosUIAxis.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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.*; @@ -48,7 +48,11 @@ public class AltosUIAxis extends NumberAxis { 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) { diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java index 0e82cacb..9c0f3bc7 100644 --- a/altosuilib/AltosUIConfigure.java +++ b/altosuilib/AltosUIConfigure.java @@ -15,7 +15,7 @@ * 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.*; @@ -223,6 +223,31 @@ public class AltosUIConfigure 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() { } @@ -257,7 +282,9 @@ public class AltosUIConfigure 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 */ diff --git a/altosuilib/AltosUIDataMissing.java b/altosuilib/AltosUIDataMissing.java index 353ff30f..9a810a41 100644 --- a/altosuilib/AltosUIDataMissing.java +++ b/altosuilib/AltosUIDataMissing.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; public class AltosUIDataMissing extends Exception { public int id; diff --git a/altosuilib/AltosUIDataPoint.java b/altosuilib/AltosUIDataPoint.java index 3f16500e..f72bbcd5 100644 --- a/altosuilib/AltosUIDataPoint.java +++ b/altosuilib/AltosUIDataPoint.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; public interface AltosUIDataPoint { public abstract double x() throws AltosUIDataMissing; diff --git a/altosuilib/AltosUIDataSet.java b/altosuilib/AltosUIDataSet.java index ee70a3fd..9e048587 100644 --- a/altosuilib/AltosUIDataSet.java +++ b/altosuilib/AltosUIDataSet.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; public interface AltosUIDataSet { public abstract String name(); diff --git a/altosuilib/AltosUIDialog.java b/altosuilib/AltosUIDialog.java index dc737414..9fc5283e 100644 --- a/altosuilib/AltosUIDialog.java +++ b/altosuilib/AltosUIDialog.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java index da98797a..e227d2b7 100644 --- a/altosuilib/AltosUIEnable.java +++ b/altosuilib/AltosUIEnable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import java.awt.event.*; @@ -23,7 +23,7 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosuilib/AltosUIFlightTab.java b/altosuilib/AltosUIFlightTab.java index 039d83e0..74161634 100644 --- a/altosuilib/AltosUIFlightTab.java +++ b/altosuilib/AltosUIFlightTab.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java index 6e62c762..2e886932 100644 --- a/altosuilib/AltosUIFrame.java +++ b/altosuilib/AltosUIFrame.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import java.awt.event.*; @@ -36,12 +36,12 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi } 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; @@ -157,11 +157,72 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi } } + 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(); } diff --git a/altosuilib/AltosFreqList.java b/altosuilib/AltosUIFreqList.java index e1299aae..84e6dce4 100644 --- a/altosuilib/AltosFreqList.java +++ b/altosuilib/AltosUIFreqList.java @@ -15,12 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import javax.swing.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; -public class AltosFreqList extends JComboBox<AltosFrequency> { +public class AltosUIFreqList extends JComboBox<AltosFrequency> { String product; int serial; @@ -53,6 +53,7 @@ public class AltosFreqList extends JComboBox<AltosFrequency> { AltosUIPreferences.add_common_frequency(frequency); insertItemAt(frequency, i); setMaximumRowCount(getItemCount()); + setVisible(true); } public void set_product(String new_product) { @@ -70,7 +71,7 @@ public class AltosFreqList extends JComboBox<AltosFrequency> { return 434.550; } - public AltosFreqList () { + public AltosUIFreqList () { super(AltosUIPreferences.common_frequencies()); setMaximumRowCount(getItemCount()); setEditable(false); @@ -78,7 +79,7 @@ public class AltosFreqList extends JComboBox<AltosFrequency> { serial = 0; } - public AltosFreqList(double in_frequency) { + public AltosUIFreqList(double in_frequency) { this(); set_frequency(in_frequency); } diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java index 9cca088d..870c4e93 100644 --- a/altosuilib/AltosUIGraph.java +++ b/altosuilib/AltosUIGraph.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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.*; diff --git a/altosuilib/AltosUIGrapher.java b/altosuilib/AltosUIGrapher.java index 724fac18..39accab4 100644 --- a/altosuilib/AltosUIGrapher.java +++ b/altosuilib/AltosUIGrapher.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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.*; diff --git a/altosuilib/AltosUIIndicator.java b/altosuilib/AltosUIIndicator.java index b1626cba..d17078e7 100644 --- a/altosuilib/AltosUIIndicator.java +++ b/altosuilib/AltosUIIndicator.java @@ -15,11 +15,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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; diff --git a/altosuilib/AltosUILatLon.java b/altosuilib/AltosUILatLon.java index 688dd58b..a15bf19f 100644 --- a/altosuilib/AltosUILatLon.java +++ b/altosuilib/AltosUILatLon.java @@ -15,7 +15,7 @@ * 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.*; @@ -25,7 +25,7 @@ import java.lang.Math; 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; diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java index b51c5963..8fa7dfe6 100644 --- a/altosuilib/AltosUILib.java +++ b/altosuilib/AltosUILib.java @@ -15,12 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 { @@ -80,6 +80,7 @@ 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" }; @@ -96,6 +97,13 @@ public class AltosUILib extends AltosLib { loaded_library = false; } } + + String OS = System.getProperty("os.name"); + + if (OS.startsWith("Linux")) { + has_bluetooth = true; + } + initialized = true; } return loaded_library; diff --git a/altosuilib/AltosUIListener.java b/altosuilib/AltosUIListener.java index 75a0ad94..a32d310c 100644 --- a/altosuilib/AltosUIListener.java +++ b/altosuilib/AltosUIListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; public interface AltosUIListener { public void ui_changed(String look_and_feel); diff --git a/altosuilib/AltosUIMap.java b/altosuilib/AltosUIMap.java index aaa68f23..c22801f8 100644 --- a/altosuilib/AltosUIMap.java +++ b/altosuilib/AltosUIMap.java @@ -15,7 +15,7 @@ * 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.*; @@ -25,7 +25,7 @@ import java.lang.Math; 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 { diff --git a/altosuilib/AltosUIMapCache.java b/altosuilib/AltosUIMapCache.java index 55311d8c..b9064cf4 100644 --- a/altosuilib/AltosUIMapCache.java +++ b/altosuilib/AltosUIMapCache.java @@ -15,7 +15,7 @@ * 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; @@ -24,30 +24,31 @@ import java.awt.*; 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; @@ -109,6 +110,28 @@ public class AltosUIMapCache { } } + 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); } } diff --git a/altosuilib/AltosUIMapCacheListener.java b/altosuilib/AltosUIMapCacheListener.java new file mode 100644 index 00000000..680d123e --- /dev/null +++ b/altosuilib/AltosUIMapCacheListener.java @@ -0,0 +1,22 @@ +/* + * 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); +} diff --git a/altosuilib/AltosUIMapImage.java b/altosuilib/AltosUIMapImage.java index 3819d079..77cd4299 100644 --- a/altosuilib/AltosUIMapImage.java +++ b/altosuilib/AltosUIMapImage.java @@ -15,7 +15,7 @@ * 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; diff --git a/altosuilib/AltosUIMapLine.java b/altosuilib/AltosUIMapLine.java index e09a2d9f..32437d4e 100644 --- a/altosuilib/AltosUIMapLine.java +++ b/altosuilib/AltosUIMapLine.java @@ -15,7 +15,7 @@ * 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.*; @@ -25,12 +25,13 @@ import java.lang.Math; 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; @@ -87,19 +88,24 @@ public class AltosUIMapLine { } 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()); @@ -111,6 +117,13 @@ public class AltosUIMapLine { } 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); } } diff --git a/altosuilib/AltosUIMapMark.java b/altosuilib/AltosUIMapMark.java index 8c640e5f..47fc4d5e 100644 --- a/altosuilib/AltosUIMapMark.java +++ b/altosuilib/AltosUIMapMark.java @@ -15,7 +15,7 @@ * 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.*; @@ -25,7 +25,7 @@ import java.lang.Math; import java.awt.geom.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosUIMapMark { diff --git a/altosuilib/AltosUIMapPath.java b/altosuilib/AltosUIMapPath.java index ff17be67..705f4b6a 100644 --- a/altosuilib/AltosUIMapPath.java +++ b/altosuilib/AltosUIMapPath.java @@ -15,7 +15,7 @@ * 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.*; @@ -25,7 +25,7 @@ import java.lang.Math; 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; diff --git a/altosuilib/AltosUIMapPreload.java b/altosuilib/AltosUIMapPreload.java index 56066d70..1c088a49 100644 --- a/altosuilib/AltosUIMapPreload.java +++ b/altosuilib/AltosUIMapPreload.java @@ -15,7 +15,7 @@ * 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.*; @@ -26,7 +26,7 @@ import java.text.*; 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; diff --git a/altosuilib/AltosUIMapRectangle.java b/altosuilib/AltosUIMapRectangle.java index 8a5b16e1..463ef3f2 100644 --- a/altosuilib/AltosUIMapRectangle.java +++ b/altosuilib/AltosUIMapRectangle.java @@ -15,7 +15,7 @@ * 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; diff --git a/altosuilib/AltosUIMapStore.java b/altosuilib/AltosUIMapStore.java index 4cecb54f..dd8ace32 100644 --- a/altosuilib/AltosUIMapStore.java +++ b/altosuilib/AltosUIMapStore.java @@ -15,7 +15,7 @@ * 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.*; diff --git a/altosuilib/AltosUIMapStoreListener.java b/altosuilib/AltosUIMapStoreListener.java index 91aff00c..0bbd2bc9 100644 --- a/altosuilib/AltosUIMapStoreListener.java +++ b/altosuilib/AltosUIMapStoreListener.java @@ -15,7 +15,7 @@ * 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); diff --git a/altosuilib/AltosUIMapTile.java b/altosuilib/AltosUIMapTile.java index 7c823183..8b6a8f0a 100644 --- a/altosuilib/AltosUIMapTile.java +++ b/altosuilib/AltosUIMapTile.java @@ -15,7 +15,7 @@ * 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.*; @@ -25,7 +25,7 @@ import java.awt.geom.*; 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; diff --git a/altosuilib/AltosUIMapTileListener.java b/altosuilib/AltosUIMapTileListener.java index 4ca13539..f58f55e0 100644 --- a/altosuilib/AltosUIMapTileListener.java +++ b/altosuilib/AltosUIMapTileListener.java @@ -15,7 +15,7 @@ * 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); diff --git a/altosuilib/AltosUIMapTransform.java b/altosuilib/AltosUIMapTransform.java index e6f1ffe3..89a3e9f6 100644 --- a/altosuilib/AltosUIMapTransform.java +++ b/altosuilib/AltosUIMapTransform.java @@ -15,7 +15,7 @@ * 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.*; @@ -25,7 +25,7 @@ import java.lang.Math; import java.awt.geom.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class AltosUIMapTransform { diff --git a/altosuilib/AltosUIMapView.java b/altosuilib/AltosUIMapView.java index a14fde65..70b8e2e9 100644 --- a/altosuilib/AltosUIMapView.java +++ b/altosuilib/AltosUIMapView.java @@ -15,7 +15,7 @@ * 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.*; @@ -26,7 +26,7 @@ import java.lang.*; 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 { @@ -67,7 +67,7 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo 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(); @@ -370,7 +370,7 @@ public class AltosUIMapView extends Component implements MouseMotionListener, Mo 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); diff --git a/altosuilib/AltosUIMapZoomListener.java b/altosuilib/AltosUIMapZoomListener.java index 02e8bb51..23498c89 100644 --- a/altosuilib/AltosUIMapZoomListener.java +++ b/altosuilib/AltosUIMapZoomListener.java @@ -15,7 +15,7 @@ * 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); diff --git a/altosuilib/AltosUIMarker.java b/altosuilib/AltosUIMarker.java index cd6fa589..5e9809ee 100644 --- a/altosuilib/AltosUIMarker.java +++ b/altosuilib/AltosUIMarker.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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.*; diff --git a/altosuilib/AltosUIPreferences.java b/altosuilib/AltosUIPreferences.java index 7a582a7d..ecab20d4 100644 --- a/altosuilib/AltosUIPreferences.java +++ b/altosuilib/AltosUIPreferences.java @@ -15,13 +15,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 { @@ -34,6 +34,9 @@ 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; @@ -52,6 +55,10 @@ public class AltosUIPreferences extends AltosPreferences { 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()); @@ -68,6 +75,9 @@ public class AltosUIPreferences extends AltosPreferences { 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(); } @@ -215,4 +225,32 @@ public class AltosUIPreferences extends AltosPreferences { 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; + } + } } diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java index da29253d..4048fd83 100644 --- a/altosuilib/AltosUIPreferencesBackend.java +++ b/altosuilib/AltosUIPreferencesBackend.java @@ -15,11 +15,11 @@ * 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 { diff --git a/altosuilib/AltosUIRateList.java b/altosuilib/AltosUIRateList.java new file mode 100644 index 00000000..ee35ce6d --- /dev/null +++ b/altosuilib/AltosUIRateList.java @@ -0,0 +1,61 @@ +/* + * 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); + } +} diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java index b0632d18..809020c4 100644 --- a/altosuilib/AltosUISeries.java +++ b/altosuilib/AltosUISeries.java @@ -15,14 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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.*; diff --git a/altosuilib/AltosUITelemetryList.java b/altosuilib/AltosUITelemetryList.java new file mode 100644 index 00000000..facfdcde --- /dev/null +++ b/altosuilib/AltosUITelemetryList.java @@ -0,0 +1,47 @@ +/* + * 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(); + } +} + diff --git a/altosuilib/AltosUIUnitsIndicator.java b/altosuilib/AltosUIUnitsIndicator.java index 2285b6fc..50c30851 100644 --- a/altosuilib/AltosUIUnitsIndicator.java +++ b/altosuilib/AltosUIUnitsIndicator.java @@ -15,11 +15,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 { diff --git a/altosuilib/AltosUIVersion.java.in b/altosuilib/AltosUIVersion.java.in index 0edb5c04..9fd5757b 100644 --- a/altosuilib/AltosUIVersion.java.in +++ b/altosuilib/AltosUIVersion.java.in @@ -15,7 +15,7 @@ * 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@"; diff --git a/altosuilib/AltosUIVoltageIndicator.java b/altosuilib/AltosUIVoltageIndicator.java index 3ff17213..8e991856 100644 --- a/altosuilib/AltosUIVoltageIndicator.java +++ b/altosuilib/AltosUIVoltageIndicator.java @@ -15,11 +15,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_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 { diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index b70b5e83..f4906a73 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.util.*; import libaltosJNI.*; @@ -79,6 +79,7 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { 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; diff --git a/altosuilib/AltosVoice.java b/altosuilib/AltosVoice.java index a3995f68..e02730ba 100644 --- a/altosuilib/AltosVoice.java +++ b/altosuilib/AltosVoice.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import com.sun.speech.freetts.Voice; import com.sun.speech.freetts.VoiceManager; diff --git a/altosuilib/GrabNDrag.java b/altosuilib/GrabNDrag.java index 4426f7a3..9bccb808 100644 --- a/altosuilib/GrabNDrag.java +++ b/altosuilib/GrabNDrag.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_2; +package org.altusmetrum.altosuilib_3; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index e08fbe74..d51da91d 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -36,7 +36,6 @@ altosuilib_JAVA = \ AltosVoice.java \ AltosDisplayThread.java \ AltosDeviceUIDialog.java \ - AltosFreqList.java \ AltosSerial.java \ AltosSerialInUseException.java \ AltosConfigFreqUI.java \ @@ -68,6 +67,7 @@ altosuilib_JAVA = \ AltosUIMapPath.java \ AltosUIMapTile.java \ AltosUIMapCache.java \ + AltosUIMapCacheListener.java \ AltosUIMapImage.java \ AltosUIMapTransform.java \ AltosUIMapRectangle.java \ @@ -80,7 +80,11 @@ altosuilib_JAVA = \ AltosUIFlightTab.java \ AltosUIIndicator.java \ AltosUIUnitsIndicator.java \ - AltosUIVoltageIndicator.java + AltosUIVoltageIndicator.java \ + AltosUIFreqList.java \ + AltosUITelemetryList.java \ + AltosUIRateList.java \ + OSXAdapter.java JAR=altosuilib_$(ALTOSUILIB_VERSION).jar @@ -99,7 +103,7 @@ ICONJAR= -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \ all-local: $(JAR) clean-local: - -rm -rf $(JAVAROOT) $(JAR) + -rm -rf $(JAVAROOT) altosuilib_*.jar install-altosuilibJAVA: $(JAR) @$(NORMAL_INSTALL) diff --git a/altosuilib/OSXAdapter.java b/altosuilib/OSXAdapter.java new file mode 100755 index 00000000..23aacd78 --- /dev/null +++ b/altosuilib/OSXAdapter.java @@ -0,0 +1,206 @@ +/* + +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(); + } + } + } +} diff --git a/ao-bringup/test-easymega b/ao-bringup/test-easymega new file mode 100755 index 00000000..eabe1ee5 --- /dev/null +++ b/ao-bringup/test-easymega @@ -0,0 +1,68 @@ +#!/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 diff --git a/ao-bringup/test-easymini b/ao-bringup/test-easymini index 29139385..17e00955 100755 --- a/ao-bringup/test-easymini +++ b/ao-bringup/test-easymini @@ -19,7 +19,7 @@ ao-list | while read product serial dev; do 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) @@ -30,7 +30,7 @@ ao-list | while read product serial dev; do esac echo "Testing baro sensor" - ./test-baro "$dev" + ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev" case $? in 0) @@ -43,7 +43,7 @@ ao-list | while read product serial dev; do FLASHSIZE=1048576 echo "Testing flash" - ./test-flash "$dev" "$FLASHSIZE" + ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE" case $? in 0) diff --git a/ao-bringup/test-gps b/ao-bringup/test-gps index a1e21626..04c467b5 100755 --- a/ao-bringup/test-gps +++ b/ao-bringup/test-gps @@ -70,6 +70,7 @@ do_gps(file f) { 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]); diff --git a/ao-bringup/test-telegps b/ao-bringup/test-telegps index f3174485..9295dd06 100755 --- a/ao-bringup/test-telegps +++ b/ao-bringup/test-telegps @@ -42,7 +42,7 @@ ao-list | while read product serial dev; do exit 1 esac - echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship + echo "$PRODUCT-v$VERSION" serial "$serial" passed functional tests ret=0 ;; *) diff --git a/ao-bringup/turnon_easymega b/ao-bringup/turnon_easymega new file mode 100755 index 00000000..b313e162 --- /dev/null +++ b/ao-bringup/turnon_easymega @@ -0,0 +1,61 @@ +#!/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 $? diff --git a/ao-bringup/turnon_telemega b/ao-bringup/turnon_telemega index 39a63642..7745a8e5 100755 --- a/ao-bringup/turnon_telemega +++ b/ao-bringup/turnon_telemega @@ -54,4 +54,6 @@ echo 'E 0' > $dev SERIAL=$SERIAL ./cal-freq $dev -./cal-accel $dev +../ao-tools/ao-cal-accel/ao-cal-accel $dev + +echo 'E 1' > $dev diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum index 80193c4c..48ff1e27 100755 --- a/ao-bringup/turnon_telemetrum +++ b/ao-bringup/turnon_telemetrum @@ -1,17 +1,13 @@ #!/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." @@ -24,16 +20,16 @@ echo "TeleMetrum v$VERSION Turn-On and Calibration Program" 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 @@ -57,4 +53,6 @@ echo 'E 0' > $dev SERIAL=$SERIAL ./cal-freq $dev -./cal-accel $dev +../ao-tools/ao-cal-accel/ao-cal-accel $dev + +echo 'E 1' > $dev diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index a42988d6..2d873e50 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1,7 +1,8 @@ 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 diff --git a/ao-tools/ao-cal-accel/.gitignore b/ao-tools/ao-cal-accel/.gitignore new file mode 100644 index 00000000..73402b2b --- /dev/null +++ b/ao-tools/ao-cal-accel/.gitignore @@ -0,0 +1 @@ +ao-cal-accel diff --git a/ao-tools/ao-cal-accel/Makefile.am b/ao-tools/ao-cal-accel/Makefile.am new file mode 100644 index 00000000..d278097a --- /dev/null +++ b/ao-tools/ao-cal-accel/Makefile.am @@ -0,0 +1,11 @@ +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 diff --git a/ao-tools/ao-cal-accel/ao-cal-accel.1 b/ao-tools/ao-cal-accel/ao-cal-accel.1 new file mode 100644 index 00000000..eb75d7c7 --- /dev/null +++ b/ao-tools/ao-cal-accel/ao-cal-accel.1 @@ -0,0 +1,58 @@ +.\" +.\" Copyright © 2009 Keith Packard <keithp@keithp.com> +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, but +.\" WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +.\" General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +.\" +.\" +.TH AO-LOAD 1 "ao-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 diff --git a/ao-tools/ao-cal-accel/ao-cal-accel.c b/ao-tools/ao-cal-accel/ao-cal-accel.c new file mode 100644 index 00000000..9a988648 --- /dev/null +++ b/ao-tools/ao-cal-accel/ao-cal-accel.c @@ -0,0 +1,284 @@ +/* + * 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); +} diff --git a/ao-tools/ao-send-telem/ao-send-telem.c b/ao-tools/ao-send-telem/ao-send-telem.c index 3db44542..26c3263e 100644 --- a/ao-tools/ao-send-telem/ao-send-telem.c +++ b/ao-tools/ao-send-telem/ao-send-telem.c @@ -85,6 +85,12 @@ packet_state(union ao_telemetry_all *telem) 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; } diff --git a/ao-tools/ao-test-baro/.gitignore b/ao-tools/ao-test-baro/.gitignore new file mode 100644 index 00000000..f5fb64d4 --- /dev/null +++ b/ao-tools/ao-test-baro/.gitignore @@ -0,0 +1 @@ +ao-test-baro diff --git a/ao-tools/ao-test-baro/Makefile.am b/ao-tools/ao-test-baro/Makefile.am new file mode 100644 index 00000000..69e47529 --- /dev/null +++ b/ao-tools/ao-test-baro/Makefile.am @@ -0,0 +1,11 @@ +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 diff --git a/ao-tools/ao-test-baro/ao-test-baro.1 b/ao-tools/ao-test-baro/ao-test-baro.1 new file mode 100644 index 00000000..0004dba8 --- /dev/null +++ b/ao-tools/ao-test-baro/ao-test-baro.1 @@ -0,0 +1,56 @@ +.\" +.\" 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 diff --git a/ao-tools/ao-test-baro/ao-test-baro.c b/ao-tools/ao-test-baro/ao-test-baro.c new file mode 100644 index 00000000..e883de4a --- /dev/null +++ b/ao-tools/ao-test-baro/ao-test-baro.c @@ -0,0 +1,238 @@ +/* + * 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); +} diff --git a/ao-tools/ao-test-flash/.gitignore b/ao-tools/ao-test-flash/.gitignore new file mode 100644 index 00000000..40ab1ef3 --- /dev/null +++ b/ao-tools/ao-test-flash/.gitignore @@ -0,0 +1 @@ +ao-test-flash diff --git a/ao-tools/ao-test-flash/Makefile.am b/ao-tools/ao-test-flash/Makefile.am new file mode 100644 index 00000000..0323c282 --- /dev/null +++ b/ao-tools/ao-test-flash/Makefile.am @@ -0,0 +1,11 @@ +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 diff --git a/ao-tools/ao-test-flash/ao-test-flash.1 b/ao-tools/ao-test-flash/ao-test-flash.1 new file mode 100644 index 00000000..155bd1bf --- /dev/null +++ b/ao-tools/ao-test-flash/ao-test-flash.1 @@ -0,0 +1,59 @@ +.\" +.\" 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 diff --git a/ao-tools/ao-test-flash/ao-test-flash.c b/ao-tools/ao-test-flash/ao-test-flash.c new file mode 100644 index 00000000..cf44ae69 --- /dev/null +++ b/ao-tools/ao-test-flash/ao-test-flash.c @@ -0,0 +1,245 @@ +/* + * 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); +} diff --git a/ao-tools/ao-test-igniter/.gitignore b/ao-tools/ao-test-igniter/.gitignore new file mode 100644 index 00000000..deee445f --- /dev/null +++ b/ao-tools/ao-test-igniter/.gitignore @@ -0,0 +1 @@ +ao-test-igniter diff --git a/ao-tools/ao-test-igniter/Makefile.am b/ao-tools/ao-test-igniter/Makefile.am new file mode 100644 index 00000000..e24ed469 --- /dev/null +++ b/ao-tools/ao-test-igniter/Makefile.am @@ -0,0 +1,11 @@ +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 diff --git a/ao-tools/ao-test-igniter/ao-test-igniter.1 b/ao-tools/ao-test-igniter/ao-test-igniter.1 new file mode 100644 index 00000000..155bd1bf --- /dev/null +++ b/ao-tools/ao-test-igniter/ao-test-igniter.1 @@ -0,0 +1,59 @@ +.\" +.\" 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 diff --git a/ao-tools/ao-test-igniter/ao-test-igniter.c b/ao-tools/ao-test-igniter/ao-test-igniter.c new file mode 100644 index 00000000..6a699fe8 --- /dev/null +++ b/ao-tools/ao-test-igniter/ao-test-igniter.c @@ -0,0 +1,223 @@ +/* + * 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); +} diff --git a/ao-tools/lib/cc-convert.c b/ao-tools/lib/cc-convert.c index 8d6876a0..b82dd778 100644 --- a/ao-tools/lib/cc-convert.c +++ b/ao-tools/lib/cc-convert.c @@ -108,6 +108,29 @@ cc_altitude_to_pressure(double altitude) 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 */ diff --git a/ao-tools/lib/cc-telemetry.c b/ao-tools/lib/cc-telemetry.c index 88da7f03..45c10dcb 100644 --- a/ao-tools/lib/cc-telemetry.c +++ b/ao-tools/lib/cc-telemetry.c @@ -89,4 +89,3 @@ cc_telemetry_unparse(const union ao_telemetry_all *telemetry, char output_line[C p += 2; } } - diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index c07f8cd0..bff4b2c9 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -346,6 +346,143 @@ struct ao_log_mega { } 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 @@ -380,9 +517,30 @@ struct ao_log_mega { #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); @@ -399,6 +557,9 @@ double cc_altitude_to_pressure(double altitude); double +cc_altitude_to_temperature(double altitude); + +double cc_barometer_to_pressure(double baro); double diff --git a/configure.ac b/configure.ac index fdae9b6f..a6a9d3c5 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl 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 @@ -29,8 +29,8 @@ AC_SUBST(VERSION_DASH) 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]) @@ -459,7 +459,7 @@ xauto) 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([])], @@ -534,6 +534,10 @@ ao-tools/ao-dump-up/Makefile 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 ]) diff --git a/doc/Makefile b/doc/Makefile index c39450c7..60c63f63 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -16,7 +16,8 @@ RELNOTES=\ 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 \ @@ -61,12 +62,13 @@ SVG=\ 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 diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index c68bbac9..0785f65a 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -41,8 +41,15 @@ </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> @@ -203,6 +210,11 @@ NAR #88757, TRA #12200 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 your choice of antenna and notebook computer, TeleDongle and our @@ -231,7 +243,7 @@ NAR #88757, TRA #12200 “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 @@ -252,7 +264,7 @@ NAR #88757, TRA #12200 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 @@ -456,7 +468,7 @@ NAR #88757, TRA #12200 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. @@ -574,6 +586,16 @@ NAR #88757, TRA #12200 <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> @@ -682,6 +704,25 @@ NAR #88757, TRA #12200 <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> @@ -1362,6 +1403,178 @@ NAR #88757, TRA #12200 </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> Each flight computer logs data at 100 samples per second @@ -1431,6 +1644,12 @@ NAR #88757, TRA #12200 <entry>8MB</entry> <entry>40</entry> </row> + <row> + <entry>EasyMega</entry> + <entry>32</entry> + <entry>8MB</entry> + <entry>40</entry> + </row> </tbody> </tgroup> </table> @@ -1444,7 +1663,7 @@ NAR #88757, TRA #12200 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. @@ -1538,7 +1757,7 @@ NAR #88757, TRA #12200 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 @@ -1803,7 +2022,8 @@ NAR #88757, TRA #12200 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 @@ -2050,6 +2270,15 @@ NAR #88757, TRA #12200 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 information about the flight computer. It sends four fields as @@ -2095,15 +2324,20 @@ NAR #88757, TRA #12200 <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> @@ -2167,6 +2401,18 @@ NAR #88757, TRA #12200 </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> This selects how often APRS packets are transmitted. Set @@ -2177,6 +2423,14 @@ NAR #88757, TRA #12200 </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> Apogee delay is the number of seconds after the altimeter detects flight @@ -2260,7 +2514,7 @@ NAR #88757, TRA #12200 <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 @@ -2275,7 +2529,7 @@ NAR #88757, TRA #12200 <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 @@ -2312,7 +2566,7 @@ NAR #88757, TRA #12200 </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 @@ -3138,6 +3392,18 @@ NAR #88757, TRA #12200 </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> How often to transmit GPS information via APRS (in @@ -3150,6 +3416,14 @@ NAR #88757, TRA #12200 </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> This sets the call sign included in each telemetry packet. Set this @@ -3211,8 +3485,8 @@ NAR #88757, TRA #12200 <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. @@ -3261,7 +3535,7 @@ NAR #88757, TRA #12200 </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 @@ -3409,7 +3683,7 @@ NAR #88757, TRA #12200 </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 @@ -3418,9 +3692,9 @@ NAR #88757, TRA #12200 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> @@ -3472,15 +3746,23 @@ NAR #88757, TRA #12200 </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> @@ -3488,7 +3770,7 @@ NAR #88757, TRA #12200 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. @@ -3540,9 +3822,9 @@ NAR #88757, TRA #12200 <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> @@ -3825,12 +4107,12 @@ NAR #88757, TRA #12200 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 @@ -3884,8 +4166,8 @@ NAR #88757, TRA #12200 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: @@ -3951,14 +4233,10 @@ NAR #88757, TRA #12200 </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 @@ -4007,8 +4285,8 @@ NAR #88757, TRA #12200 <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> @@ -4218,7 +4496,7 @@ NAR #88757, TRA #12200 <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 @@ -4241,12 +4519,12 @@ NAR #88757, TRA #12200 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> @@ -4328,6 +4606,20 @@ NAR #88757, TRA #12200 </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> <para> @@ -4354,6 +4646,50 @@ NAR #88757, TRA #12200 </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> @@ -4716,6 +5052,67 @@ NAR #88757, TRA #12200 </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 </title> <itemizedlist> @@ -5273,6 +5670,21 @@ NAR #88757, TRA #12200 </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> TeleMetrum has overall dimensions of 1.000 x 2.750 inches, and the @@ -5322,7 +5734,7 @@ NAR #88757, TRA #12200 <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 @@ -5374,7 +5786,7 @@ NAR #88757, TRA #12200 </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 @@ -5401,7 +5813,7 @@ NAR #88757, TRA #12200 </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 @@ -5421,13 +5833,20 @@ NAR #88757, TRA #12200 <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 xmlns:xi="http://www.w3.org/2001/XInclude" diff --git a/doc/configure-altimeter.png b/doc/configure-altimeter.png Binary files differindex 514db3ed..09a83d16 100644 --- a/doc/configure-altimeter.png +++ b/doc/configure-altimeter.png diff --git a/doc/configure-groundstation.png b/doc/configure-groundstation.png Binary files differindex 9f836e71..9e3c98aa 100644 --- a/doc/configure-groundstation.png +++ b/doc/configure-groundstation.png diff --git a/doc/easymega-outline.xsl b/doc/easymega-outline.xsl new file mode 100644 index 00000000..5796f9c9 --- /dev/null +++ b/doc/easymega-outline.xsl @@ -0,0 +1,23 @@ +<?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 +--> diff --git a/doc/easymega-v1.0-bottom.jpg b/doc/easymega-v1.0-bottom.jpg Binary files differnew file mode 100644 index 00000000..be46f14f --- /dev/null +++ b/doc/easymega-v1.0-bottom.jpg diff --git a/doc/easymega-v1.0-top.jpg b/doc/easymega-v1.0-top.jpg Binary files differnew file mode 100644 index 00000000..4526f659 --- /dev/null +++ b/doc/easymega-v1.0-top.jpg diff --git a/doc/easymega.svg b/doc/easymega.svg new file mode 100644 index 00000000..6d9d766f --- /dev/null +++ b/doc/easymega.svg @@ -0,0 +1,33 @@ +<?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> diff --git a/doc/release-notes-1.5.xsl b/doc/release-notes-1.5.xsl new file mode 100644 index 00000000..50d83f77 --- /dev/null +++ b/doc/release-notes-1.5.xsl @@ -0,0 +1,121 @@ +<?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> diff --git a/doc/scan-channels.png b/doc/scan-channels.png Binary files differindex bf6b6e53..e45880cd 100644 --- a/doc/scan-channels.png +++ b/doc/scan-channels.png diff --git a/icon/.gitignore b/icon/.gitignore index e89555de..94c7c70c 100644 --- a/icon/.gitignore +++ b/icon/.gitignore @@ -1,6 +1,7 @@ -altus-metrum-*.png -micropeak-*.png -telegps-*.png +application-*.png +altusmetrum-*.png +*.rc *.ico *.icns *.build +*.exe diff --git a/icon/Makefile.am b/icon/Makefile.am index b1c00f4b..bf147ad3 100644 --- a/icon/Makefile.am +++ b/icon/Makefile.am @@ -3,71 +3,157 @@ MAC_RES=16 32 128 256 512 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 diff --git a/icon/altusmetrum.svg b/icon/altusmetrum-altosui.svg index e8935a65..e8935a65 100644 --- a/icon/altusmetrum.svg +++ b/icon/altusmetrum-altosui.svg diff --git a/icon/micropeak.svg b/icon/altusmetrum-micropeak.svg index d37130f5..d37130f5 100644 --- a/icon/micropeak.svg +++ b/icon/altusmetrum-micropeak.svg diff --git a/icon/telegps.svg b/icon/altusmetrum-telegps.svg index 1e390f3b..1e390f3b 100644 --- a/icon/telegps.svg +++ b/icon/altusmetrum-telegps.svg diff --git a/icon/application-vnd.altusmetrum.eeprom.svg b/icon/application-vnd.altusmetrum.eeprom.svg new file mode 100644 index 00000000..7b481cdc --- /dev/null +++ b/icon/application-vnd.altusmetrum.eeprom.svg @@ -0,0 +1,397 @@ +<?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> diff --git a/icon/application-vnd.altusmetrum.micropeak.svg b/icon/application-vnd.altusmetrum.micropeak.svg new file mode 120000 index 00000000..6efd3200 --- /dev/null +++ b/icon/application-vnd.altusmetrum.micropeak.svg @@ -0,0 +1 @@ +altusmetrum-micropeak.svg
\ No newline at end of file diff --git a/icon/application-vnd.altusmetrum.telemetry.svg b/icon/application-vnd.altusmetrum.telemetry.svg new file mode 100644 index 00000000..4bcc0850 --- /dev/null +++ b/icon/application-vnd.altusmetrum.telemetry.svg @@ -0,0 +1,397 @@ +<?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> diff --git a/icon/creating-linux-icons b/icon/creating-linux-icons new file mode 100644 index 00000000..5b034c09 --- /dev/null +++ b/icon/creating-linux-icons @@ -0,0 +1,29 @@ +# 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 diff --git a/icon/org-altusmetrum-mimetypes.xml b/icon/org-altusmetrum-mimetypes.xml new file mode 100644 index 00000000..e8103c03 --- /dev/null +++ b/icon/org-altusmetrum-mimetypes.xml @@ -0,0 +1,16 @@ +<?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> diff --git a/icon/windows-stub.c b/icon/windows-stub.c new file mode 100644 index 00000000..8df3e0aa --- /dev/null +++ b/icon/windows-stub.c @@ -0,0 +1,2 @@ +__stdcall +WinMain(int a, int b, int c, int d) { return 0; } diff --git a/libaltos/Makefile.am b/libaltos/Makefile.am index d2531133..1db2d486 100644 --- a/libaltos/Makefile.am +++ b/libaltos/Makefile.am @@ -41,8 +41,7 @@ cjnitest64_LDADD=libaltos64.la endif - -LIBS=-lbluetooth +LIBS=-ldl HFILES=libaltos.h diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c index b7ec98fc..4e3bc2c5 100644 --- a/libaltos/libaltos.c +++ b/libaltos/libaltos.c @@ -643,6 +643,49 @@ altos_list_finish(struct altos_list *usbdevs) 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; @@ -706,7 +749,8 @@ altos_bt_list_next(struct altos_bt_list *bt_list, 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), @@ -742,11 +786,17 @@ altos_bt_open(struct altos_bt_device *device) 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); diff --git a/micropeak/.gitignore b/micropeak/.gitignore index f9a61359..2cf940a6 100644 --- a/micropeak/.gitignore +++ b/micropeak/.gitignore @@ -11,7 +11,7 @@ micropeak-windows.nsi MicroPeak-Linux-* MicroPeak-Mac-* MicroPeak-Windows-* -micropeak.desktop +*.desktop *.dll *.dylib *.so diff --git a/micropeak/Info.plist.in b/micropeak/Info.plist.in index 40984c5a..b1dc6cea 100644 --- a/micropeak/Info.plist.in +++ b/micropeak/Info.plist.in @@ -23,7 +23,22 @@ <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> diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 39ebc43a..15865606 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -56,26 +56,41 @@ ALTOSUILIB_CLASS=\ 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) @@ -87,12 +102,12 @@ clean-local: $(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 @@ -106,14 +121,14 @@ DOC=$(MICROPEAK_DOC) 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) @@ -124,7 +139,7 @@ WINDOWS_DRIVER=CDM20824_Setup.exe $(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 @@ -261,7 +276,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) 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 diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index ca211f16..c38ada91 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak; import java.lang.*; import java.io.*; import java.util.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; class MicroIterator implements Iterator<MicroDataPoint> { int i; @@ -97,9 +97,15 @@ public class MicroData implements AltosUIDataSet { 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 { } @@ -172,7 +178,7 @@ public class MicroData implements AltosUIDataSet { if (get_nonwhite(f) == 'M' && get_nonwhite(f) == 'P') return true; } - } + } private int get_32(InputStream f) throws IOException, FileEndedException, NonHexcharException { int v = 0; @@ -345,6 +351,9 @@ public class MicroData implements AltosUIDataSet { 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); @@ -367,7 +376,7 @@ public class MicroData implements AltosUIDataSet { else cur = down; } - + pressures[i+1] = cur; } @@ -376,7 +385,14 @@ public class MicroData implements AltosUIDataSet { 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"); @@ -389,5 +405,5 @@ public class MicroData implements AltosUIDataSet { pressures = new int[1]; pressures[0] = 101000; } - + } diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java index 5a5e8c37..849ae536 100644 --- a/micropeak/MicroDataPoint.java +++ b/micropeak/MicroDataPoint.java @@ -17,7 +17,7 @@ package org.altusmetrum.micropeak; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; public class MicroDataPoint implements AltosUIDataPoint { public double time; diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java index 305421a7..304eac7d 100644 --- a/micropeak/MicroDeviceDialog.java +++ b/micropeak/MicroDeviceDialog.java @@ -21,7 +21,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; public class MicroDeviceDialog extends AltosDeviceDialog { diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java index 1c70e1d1..32dd0450 100644 --- a/micropeak/MicroDownload.java +++ b/micropeak/MicroDownload.java @@ -23,8 +23,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_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; diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java index 87d5499b..8d62ace6 100644 --- a/micropeak/MicroExport.java +++ b/micropeak/MicroExport.java @@ -23,8 +23,8 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class MicroExport extends JFileChooser { diff --git a/micropeak/MicroFile.java b/micropeak/MicroFile.java index 019346ae..d6abfcb7 100644 --- a/micropeak/MicroFile.java +++ b/micropeak/MicroFile.java @@ -19,8 +19,8 @@ package org.altusmetrum.micropeak; import java.io.*; import java.util.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class MicroFile { diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java index 00b6690a..371c22d0 100644 --- a/micropeak/MicroFileChooser.java +++ b/micropeak/MicroFileChooser.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class MicroFileChooser extends JFileChooser { JFrame frame; diff --git a/micropeak/MicroFrame.java b/micropeak/MicroFrame.java index 5bfe5bf7..8b3d49b5 100644 --- a/micropeak/MicroFrame.java +++ b/micropeak/MicroFrame.java @@ -21,16 +21,16 @@ import java.awt.*; 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); } diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index f9968919..811b1e7c 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -22,8 +22,8 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns b/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns Binary files differdeleted file mode 100644 index 9ba83bf5..00000000 --- a/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns +++ /dev/null diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 19e91660..1744e803 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -23,8 +23,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class MicroPeak extends MicroFrame implements ActionListener, ItemListener { @@ -107,7 +107,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene private void DownloadData() { AltosDevice device = MicroDeviceDialog.show(this); - + if (device != null) new MicroDownload(this, device); } @@ -128,7 +128,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene if (save.runDialog()) SetName(data.name); } - + private void Export() { if (data == null) { no_data(); @@ -190,10 +190,25 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene 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(); diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java index 26d62012..7a225dcb 100644 --- a/micropeak/MicroRaw.java +++ b/micropeak/MicroRaw.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak; import java.awt.*; import java.io.*; import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class MicroRaw extends JTextArea { diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java index 7c5d6abe..9497fb33 100644 --- a/micropeak/MicroSave.java +++ b/micropeak/MicroSave.java @@ -24,8 +24,8 @@ import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class MicroSave extends JFileChooser { diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java index 37b68636..f5108c22 100644 --- a/micropeak/MicroSerial.java +++ b/micropeak/MicroSerial.java @@ -20,7 +20,7 @@ package org.altusmetrum.micropeak; import java.util.*; import java.io.*; import libaltosJNI.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; public class MicroSerial extends InputStream { SWIGTYPE_p_altos_file file; diff --git a/micropeak/MicroSerialLog.java b/micropeak/MicroSerialLog.java index 7300f06d..c49b69ab 100644 --- a/micropeak/MicroSerialLog.java +++ b/micropeak/MicroSerialLog.java @@ -20,7 +20,7 @@ package org.altusmetrum.micropeak; import java.util.*; import java.io.*; import libaltosJNI.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; public interface MicroSerialLog { diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java index 45c9f225..3fc05bd6 100644 --- a/micropeak/MicroStats.java +++ b/micropeak/MicroStats.java @@ -18,8 +18,8 @@ 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; diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java index 3b17e731..d6265fe8 100644 --- a/micropeak/MicroStatsTable.java +++ b/micropeak/MicroStatsTable.java @@ -19,8 +19,8 @@ package org.altusmetrum.micropeak; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_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; diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java index 437fa0bc..24f6722b 100644 --- a/micropeak/MicroUSB.java +++ b/micropeak/MicroUSB.java @@ -19,7 +19,7 @@ package org.altusmetrum.micropeak; import java.util.*; import libaltosJNI.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; public class MicroUSB extends altos_device implements AltosDevice { diff --git a/micropeak/micropeak.desktop.in b/micropeak/altusmetrum-micropeak.desktop.in index abdf286f..782b4704 100644 --- a/micropeak/micropeak.desktop.in +++ b/micropeak/altusmetrum-micropeak.desktop.in @@ -1,10 +1,10 @@ [Desktop Entry] Type=Application Name=MicroPeak -GenericName=MicroPeak download and analysis +GenericName=MicroPeak Download and Analysis Comment=View and log data from MicroPeak altimeters -Icon=%icondir%/micropeak.svg +Icon=%icondir%/altusmetrum-micropeak.svg Exec=%bindir%/micropeak %f Terminal=false -MimeType=text/plain; +MimeType=application/vnd.altusmetrum.micropeak Categories=Education;Electronics;Science; diff --git a/micropeak/micropeak-windows.nsi.in b/micropeak/micropeak-windows.nsi.in index bb5da1bb..848523b0 100644 --- a/micropeak/micropeak-windows.nsi.in +++ b/micropeak/micropeak-windows.nsi.in @@ -1,15 +1,24 @@ -!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" @@ -19,7 +28,7 @@ RequestExecutionLevel admin ShowInstDetails Show -ComponentText "Altus Metrum MicroPeak Software Installer" +ComponentText "${REG_NAME} Software and Driver Installer" Function .onInit DetailPrint "Checking host operating system" @@ -31,6 +40,16 @@ Function .onInit ${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 @@ -43,12 +62,21 @@ UninstPage instfiles ; 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" @@ -56,22 +84,13 @@ Section "MicroPeak Application" 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" @@ -81,33 +100,79 @@ 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 diff --git a/src/Makefile b/src/Makefile index 4e8b3c20..20126de6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -22,9 +22,11 @@ SDCCDIRS=\ 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 \ @@ -39,7 +41,7 @@ ARMM0DIRS=\ 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= @@ -98,7 +100,7 @@ uninstall: 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 $< > $@ @@ -106,7 +108,10 @@ altitude.h: make-altitude 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 diff --git a/src/cc1111/ao_intflash.c b/src/cc1111/ao_intflash.c index 632e2a85..eb3535c6 100644 --- a/src/cc1111/ao_intflash.c +++ b/src/cc1111/ao_intflash.c @@ -129,6 +129,8 @@ ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentra nop _endasm; } + __critical while (!ao_intflash_dma_done) + ao_sleep(&ao_intflash_dma_done); } static void diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 2b19f1f6..e12f813f 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -20,6 +20,8 @@ #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 */ @@ -56,6 +58,9 @@ #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) @@ -96,6 +101,9 @@ #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) @@ -136,6 +144,9 @@ #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) @@ -164,6 +175,8 @@ #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) @@ -193,6 +206,8 @@ #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) @@ -220,6 +235,8 @@ #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) @@ -252,6 +269,8 @@ #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 @@ -283,6 +302,7 @@ #define LEGACY_MONITOR 1 #define HAS_RSSI 1 #define HAS_AES 0 + #define HAS_TELEMETRY 0 #endif #if defined(TIDONGLE) @@ -312,6 +332,7 @@ #define LEGACY_MONITOR 1 #define HAS_RSSI 1 #define HAS_AES 0 + #define HAS_TELEMETRY 0 #endif #if defined(TELEBT_V_0_0) @@ -350,6 +371,8 @@ #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) @@ -396,6 +419,8 @@ #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) @@ -428,6 +453,7 @@ #define HAS_IGNITE 1 #define HAS_MONITOR 0 #define HAS_AES 1 + #define HAS_TELEMETRY 0 #endif #if DBG_ON_P1 diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 190647ce..b9821a42 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -40,6 +40,42 @@ #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) @@ -47,7 +83,9 @@ * 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 /* @@ -55,22 +93,41 @@ * * 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), @@ -122,13 +179,10 @@ static __code uint8_t radio_setup[] = { 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)), @@ -136,9 +190,6 @@ static __code uint8_t radio_setup[] = { 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 */ @@ -155,8 +206,8 @@ static __code uint8_t radio_setup[] = { 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 */ @@ -187,10 +238,16 @@ static __code uint8_t radio_setup[] = { 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, @@ -198,7 +255,7 @@ static __code uint8_t radio_setup[] = { 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 | @@ -212,26 +269,30 @@ static __code uint8_t rdf_setup[] = { (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)| @@ -243,6 +304,38 @@ static __code uint8_t fixed_pkt_setup[] = { 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; @@ -308,6 +401,10 @@ ao_radio_get(uint8_t len) 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 } @@ -551,8 +648,31 @@ ao_radio_test_cmd(void) 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 }, }; diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index 80d3fb70..ac1e71c9 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -1165,12 +1165,73 @@ __xdata __at (0xdf16) uint8_t RF_BSCFG; __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 diff --git a/src/drivers/ao_aprs.c b/src/drivers/ao_aprs.c index 8a1b6a4d..19beb78f 100644 --- a/src/drivers/ao_aprs.c +++ b/src/drivers/ao_aprs.c @@ -1,11 +1,11 @@ -/** +/** * 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. @@ -24,7 +24,7 @@ * (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), @@ -38,7 +38,7 @@ * (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. * @@ -54,28 +54,28 @@ * (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. - * + * * @@ -102,11 +102,11 @@ * You should have received a copy of the GNU General Public 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. @@ -118,29 +118,33 @@ * @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> @@ -176,11 +180,11 @@ static uint16_t sysCRC16(const uint8_t *buffer, uint8_t length, uint16_t crc) { 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 ); @@ -253,7 +257,7 @@ typedef enum /// 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, @@ -261,6 +265,7 @@ static uint8_t TNC_AX25_HEADER[] = { #define TNC_CALLSIGN_OFF 7 #define TNC_CALLSIGN_LEN 6 +#define TNC_SSID_OFF 13 static void tncSetCallsign(void) @@ -275,6 +280,9 @@ 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 } @@ -302,7 +310,7 @@ static uint8_t tncBitStuff; /// 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() @@ -323,7 +331,7 @@ static void tnc1200TimerTick() else timeNCOFreq = 0x3aab; - switch (tncMode) + switch (tncMode) { case TNC_TX_READY: // Generate a test signal alteranting between high and low tones. @@ -339,16 +347,16 @@ static void tnc1200TimerTick() 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]; @@ -361,7 +369,7 @@ static void tnc1200TimerTick() 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; @@ -381,17 +389,17 @@ static void tnc1200TimerTick() 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]; @@ -406,7 +414,7 @@ static void tnc1200TimerTick() 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; @@ -426,17 +434,17 @@ static void tnc1200TimerTick() 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; @@ -451,7 +459,7 @@ static void tnc1200TimerTick() 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; @@ -460,13 +468,13 @@ static void tnc1200TimerTick() } // 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; @@ -530,6 +538,7 @@ static int tncComment(uint8_t *buf) #ifdef AO_SENSE_MAIN " M%d.%d" #endif + " %d" , ao_gps_locked(), ao_num_sats(), battery/10, @@ -542,6 +551,7 @@ static int tncComment(uint8_t *buf) , main/10, main%10 #endif + , ao_serial_number ); #else return sprintf((char *) buf, @@ -703,7 +713,7 @@ static int tncPositionPacket(void) 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; } @@ -759,7 +769,7 @@ tncFill(uint8_t *buf, int16_t len) return l; } -/** +/** * Prepare an AX.25 data packet. Each time this method is called, it automatically * rotates through 1 of 3 messages. * diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 31225939..3ea8b704 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -41,8 +41,10 @@ extern const uint32_t ao_radio_cal; #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) @@ -107,7 +109,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) } 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; @@ -124,8 +126,8 @@ ao_radio_burst_read_start (uint16_t addr) addr); d = 1; } - ao_radio_select(); - ao_radio_spi_send(data, d); + + ao_radio_spi_send_sync(data, d); } static void @@ -209,7 +211,7 @@ ao_radio_tx_fifo_space(void) return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES); } -#if 0 +#if CC1120_DEBUG static uint8_t ao_radio_status(void) { @@ -245,7 +247,7 @@ ao_radio_check_marc_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; @@ -275,48 +277,102 @@ static void 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) | @@ -335,6 +391,39 @@ static const uint16_t packet_setup[] = { 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)), @@ -397,6 +486,7 @@ static const uint16_t rdf_setup[] = { (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, }; /* @@ -443,6 +533,7 @@ static const uint16_t aprs_setup[] = { (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, }; /* @@ -506,23 +597,48 @@ static uint16_t ao_radio_mode; #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); @@ -530,20 +646,16 @@ ao_radio_set_mode(uint16_t new_mode) 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); @@ -563,12 +675,9 @@ static uint8_t ao_radio_configured = 0; 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; @@ -592,6 +701,7 @@ static void ao_radio_get(uint8_t len) { static uint32_t last_radio_setting; + static uint8_t last_radio_rate; ao_mutex_get(&ao_radio_mutex); @@ -603,6 +713,10 @@ ao_radio_get(uint8_t len) 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); } @@ -696,7 +810,7 @@ ao_radio_test_cmd(void) 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)); @@ -793,7 +907,7 @@ ao_radio_send(const void *d, uint8_t size) } 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(); @@ -881,6 +995,11 @@ static uint16_t rx_data_consumed; 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; @@ -895,13 +1014,34 @@ ao_radio_rx_isr(void) { 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) @@ -920,24 +1060,20 @@ ao_radio_rx_isr(void) 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 @@ -977,48 +1113,67 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) */ 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 */ @@ -1033,7 +1188,7 @@ abort: radio_rssi = AO_RADIO_FROM_RSSI (rssi); } - ao_radio_strobe(CC1120_SIDLE); + ao_radio_idle(); ao_radio_put(); @@ -1072,7 +1227,7 @@ struct ao_cc1120_reg { 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" }, @@ -1253,7 +1408,7 @@ const static struct ao_cc1120_reg ao_cc1120_reg[] = { 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(); @@ -1264,6 +1419,10 @@ static void ao_radio_show(void) { 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(); } @@ -1287,12 +1446,12 @@ static void ao_radio_packet(void) { } 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 @@ -1308,13 +1467,12 @@ ao_radio_test_recv() #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[] = { diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index a1d78c01..943f3449 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -189,6 +189,12 @@ #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 @@ -294,7 +300,7 @@ #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 diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index 399abc4d..21a31a89 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -31,20 +31,23 @@ CC1120_SYNC0, 0x91, /* Sync Word Configuration [7:0] */
CC1120_SYNC_CFG1, /* Sync Word Detection Configuration */
- (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED << CC1120_SYNC_CFG1_DEM_CFG) |
- (0x07 << CC1120_SYNC_CFG1_SYNC_THR),
+ (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_DISABLED << CC1120_SYNC_CFG1_DEM_CFG) |
+ (0xc << CC1120_SYNC_CFG1_SYNC_THR),
CC1120_SYNC_CFG0,
(CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) |
- (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR),
- CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */
+ (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_DISABLED << CC1120_SYNC_CFG0_SYNC_NUM_ERROR),
+ CC1120_DCFILT_CFG, 0x15, /* Digital DC Removal Configuration */
CC1120_PREAMBLE_CFG1, /* Preamble Length Configuration */
(CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
(CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD),
CC1120_PREAMBLE_CFG0,
- (1 << CC1120_PREAMBLE_CFG0_PQT_EN) |
- (0x6 << CC1120_PREAMBLE_CFG0_PQT),
- CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */
- CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */
+ (0 << CC1120_PREAMBLE_CFG0_PQT_EN) |
+ (0xe << CC1120_PREAMBLE_CFG0_PQT),
+
+ /* Adjust PQT lower to accept fewer packets */
+
+ CC1120_FREQ_IF_CFG, 0x3a, /* RX Mixer Frequency Configuration */
+ CC1120_IQIC, 0x00, /* Digital Image Channel Compensation Configuration */
CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */
CC1120_MDMCFG1, /* General Modem Parameter Configuration */
@@ -53,12 +56,12 @@ (0 << CC1120_MDMCFG1_MANCHESTER_EN) |
(0 << CC1120_MDMCFG1_INVERT_DATA_EN) |
(0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) |
- (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) |
+ (CC1120_MDMCFG1_DVGA_GAIN_0 << CC1120_MDMCFG1_DVGA_GAIN) |
(0 << CC1120_MDMCFG1_SINGLE_ADC_EN),
- CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */
+ CC1120_MDMCFG0, 0x0d, /* General Modem Parameter Configuration */
/* AGC reference = 10 * log10(receive BW) - 4 = 10 * log10(100e3) - 4 = 46 */
- CC1120_AGC_REF, 46, /* AGC Reference Level Configuration */
+ CC1120_AGC_REF, 0x36, /* AGC Reference Level Configuration */
/* Carrier sense threshold - 25dB above the noise */
CC1120_AGC_CS_THR, 25, /* Carrier Sense Threshold Configuration */
@@ -93,7 +96,7 @@ CC1120_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */
(CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) |
- (CC1120_SETTLING_CFG_LOCK_TIME_50_20 << CC1120_SETTLING_CFG_LOCK_TIME) |
+ (CC1120_SETTLING_CFG_LOCK_TIME_75_30 << CC1120_SETTLING_CFG_LOCK_TIME) |
(CC1120_SETTLING_CFG_FSREG_TIME_60 << CC1120_SETTLING_CFG_FSREG_TIME),
CC1120_FS_CFG, /* Frequency Synthesizer Configuration */
@@ -109,7 +112,7 @@ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */
CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */
#endif
- CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */
+ CC1120_RFEND_CFG1, 0x0e, /* RFEND Configuration, Reg 1 */
CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */
// CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */
CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */
@@ -117,8 +120,8 @@ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */
CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */
CC1120_IF_MIX_CFG, 0x00, /* IF Mix Configuration */
- CC1120_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */
- CC1120_TOC_CFG, 0x0b, /* Timing Offset Correction Configuration */
+ CC1120_FREQOFF_CFG, 0x20, /* Frequency Offset Correction Configuration */
+ CC1120_TOC_CFG, 0x0a, /* Timing Offset Correction Configuration */
CC1120_MARC_SPARE, 0x00, /* MARC Spare */
CC1120_ECG_CFG, 0x00, /* External Clock Frequency Configuration */
CC1120_SOFT_TX_DATA_CFG, 0x00, /* Soft TX Data Configuration */
@@ -167,7 +170,7 @@ CC1120_XOSC4, 0xa0, /* Crystal Oscillator Configuration, Reg 4 */
CC1120_XOSC3, 0x03, /* Crystal Oscillator Configuration, Reg 3 */
CC1120_XOSC2, 0x04, /* Crystal Oscillator Configuration, Reg 2 */
- CC1120_XOSC1, 0x01, /* Crystal Oscillator Configuration, Reg 1 */
+ CC1120_XOSC1, 0x03, /* Crystal Oscillator Configuration, Reg 1 */
CC1120_XOSC0, 0x00, /* Crystal Oscillator Configuration, Reg 0 */
CC1120_ANALOG_SPARE, 0x00, /* */
CC1120_PA_CFG3, 0x00, /* Power Amplifier Configuration, Reg 3 */
@@ -196,31 +199,10 @@ CC1120_AGC_GAIN2, 0xd1, /* AGC Gain, Reg 2 */
CC1120_AGC_GAIN1, 0x00, /* AGC Gain, Reg 1 */
CC1120_AGC_GAIN0, 0x3f, /* AGC Gain, Reg 0 */
- CC1120_SOFT_RX_DATA_OUT, 0x00, /* Soft Decision Symbol Data */
- CC1120_SOFT_TX_DATA_IN, 0x00, /* Soft TX Data Input Register */
- CC1120_ASK_SOFT_RX_DATA, 0x30, /* AGC ASK Soft Decision Output */
CC1120_RNDGEN, 0x7f, /* Random Number Value */
- CC1120_MAGN2, 0x00, /* Signal Magnitude after CORDIC [16] */
- CC1120_MAGN1, 0x00, /* Signal Magnitude after CORDIC [15:8] */
- CC1120_MAGN0, 0x00, /* Signal Magnitude after CORDIC [7:0] */
- CC1120_ANG1, 0x00, /* Signal Angular after CORDIC [9:8] */
- CC1120_ANG0, 0x00, /* Signal Angular after CORDIC [7:0] */
- CC1120_CHFILT_I2, 0x08, /* Channel Filter Data Real Part [18:16] */
- CC1120_CHFILT_I1, 0x00, /* Channel Filter Data Real Part [15:8] */
- CC1120_CHFILT_I0, 0x00, /* Channel Filter Data Real Part [7:0] */
- CC1120_CHFILT_Q2, 0x00, /* Channel Filter Data Imaginary Part [18:16] */
- CC1120_CHFILT_Q1, 0x00, /* Channel Filter Data Imaginary Part [15:8] */
- CC1120_CHFILT_Q0, 0x00, /* Channel Filter Data Imaginary Part [7:0] */
- CC1120_GPIO_STATUS, 0x00, /* GPIO Status */
CC1120_FSCAL_CTRL, 0x01, /* */
CC1120_PHASE_ADJUST, 0x00, /* */
- CC1120_PARTNUMBER, 0x00, /* Part Number */
- CC1120_PARTVERSION, 0x00, /* Part Revision */
CC1120_SERIAL_STATUS, 0x00, /* Serial Status */
- CC1120_RX_STATUS, 0x01, /* RX Status */
- CC1120_TX_STATUS, 0x00, /* TX Status */
- CC1120_MARC_STATUS1, 0x00, /* MARC Status, Reg 1 */
- CC1120_MARC_STATUS0, 0x00, /* MARC Status, Reg 0 */
CC1120_PA_IFAMP_TEST, 0x00, /* */
CC1120_FSRF_TEST, 0x00, /* */
CC1120_PRE_TEST, 0x00, /* */
diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index f250e714..cf61acfe 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -249,36 +249,81 @@ ao_radio_idle(void) } /* - * 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) | @@ -403,9 +448,13 @@ ao_radio_set_mode(uint16_t new_mode) 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) @@ -494,6 +543,7 @@ static void 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) @@ -504,6 +554,10 @@ ao_radio_get(void) 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 diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 944a37f9..066df6ff 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -278,16 +278,17 @@ ao_nmea_gga(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(); diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index 077698a9..74c29e0a 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -728,7 +728,7 @@ ao_gps(void) __reentrant 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; @@ -740,11 +740,11 @@ ao_gps(void) __reentrant 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; diff --git a/src/drivers/ao_lco_func.c b/src/drivers/ao_lco_func.c index 9e642836..32c00068 100644 --- a/src/drivers/ao_lco_func.c +++ b/src/drivers/ao_lco_func.c @@ -28,7 +28,21 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset) { 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; @@ -36,7 +50,7 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset) 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); diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index d6c99cbd..23545049 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -57,6 +57,12 @@ static __xdata uint16_t ao_packet_master_time; #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) { @@ -91,7 +97,7 @@ ao_packet_master(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) { diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 144cbd70..dc2c83fe 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -362,14 +362,26 @@ ao_pad_test(void) 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; diff --git a/src/easymega-v0.1/.gitignore b/src/easymega-v1.0/.gitignore index 410943d5..410943d5 100644 --- a/src/easymega-v0.1/.gitignore +++ b/src/easymega-v1.0/.gitignore diff --git a/src/easymega-v0.1/Makefile b/src/easymega-v1.0/Makefile index 66619852..c3b360b4 100644 --- a/src/easymega-v0.1/Makefile +++ b/src/easymega-v1.0/Makefile @@ -107,13 +107,13 @@ ALTOS_SRC = \ $(SAMPLE_PROFILE) \ $(STACK_GUARD) -PRODUCT=EasyMega-v0.1 +PRODUCT=EasyMega-v1.0 PRODUCT_DEF=-DEASYMEGA -IDPRODUCT=0x0023 +IDPRODUCT=0x0028 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g -PROGNAME=easymega-v0.1 +PROGNAME=easymega-v1.0 PROG=$(PROGNAME)-$(VERSION).elf HEX=$(PROGNAME)-$(VERSION).ihx diff --git a/src/easymega-v0.1/ao_easymega.c b/src/easymega-v1.0/ao_easymega.c index e217c33c..e217c33c 100644 --- a/src/easymega-v0.1/ao_easymega.c +++ b/src/easymega-v1.0/ao_easymega.c diff --git a/src/easymega-v0.1/ao_pins.h b/src/easymega-v1.0/ao_pins.h index cb6e3980..d6490ba5 100644 --- a/src/easymega-v0.1/ao_pins.h +++ b/src/easymega-v1.0/ao_pins.h @@ -65,6 +65,9 @@ #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 diff --git a/src/easymega-v0.1/flash-loader/Makefile b/src/easymega-v1.0/flash-loader/Makefile index 35312fd6..d83cb70a 100644 --- a/src/easymega-v0.1/flash-loader/Makefile +++ b/src/easymega-v1.0/flash-loader/Makefile @@ -4,5 +4,5 @@ # TOPDIR=../.. -HARDWARE=easymega-v0.1 +HARDWARE=easymega-v1.0 include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/easymega-v0.1/flash-loader/ao_pins.h b/src/easymega-v1.0/flash-loader/ao_pins.h index 445289bf..445289bf 100644 --- a/src/easymega-v0.1/flash-loader/ao_pins.h +++ b/src/easymega-v1.0/flash-loader/ao_pins.h diff --git a/src/kalman/kalman.5c b/src/kalman/kalman.5c index 46fa8e1f..55fde04c 100755 --- a/src/kalman/kalman.5c +++ b/src/kalman/kalman.5c @@ -457,7 +457,7 @@ void main() { 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); diff --git a/src/kalman/kalman_micro.5c b/src/kalman/kalman_micro.5c index 266a1182..1b080384 100644 --- a/src/kalman/kalman_micro.5c +++ b/src/kalman/kalman_micro.5c @@ -307,7 +307,7 @@ void main() { 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); diff --git a/src/kernel/ao.h b/src/kernel/ao.h index 5ff9b518..ad5bbf8e 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -132,6 +132,9 @@ ao_clock_init(void); */ #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; @@ -275,15 +278,17 @@ ao_report_init(void); * 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 @@ -293,11 +298,13 @@ ao_temp_to_dC(int16_t temp) __reentrant; #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> @@ -522,6 +529,9 @@ struct ao_telemetry_raw_recv { #endif void +ao_telemetry_reset_interval(void); + +void ao_telemetry_set_interval(uint16_t interval); void @@ -558,6 +568,15 @@ extern __xdata int8_t ao_radio_rssi; #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); @@ -757,11 +776,13 @@ extern __xdata uint8_t ao_force_freq; * 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 diff --git a/src/kernel/ao_cmd.c b/src/kernel/ao_cmd.c index 0052bdce..d2f583ef 100644 --- a/src/kernel/ao_cmd.c +++ b/src/kernel/ao_cmd.c @@ -290,6 +290,9 @@ version(void) #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 , ao_serial_number diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 71445335..6b8a1813 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -50,17 +50,25 @@ __xdata uint8_t ao_config_mutex; #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 @@ -85,10 +93,18 @@ ao_config_put(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 */ @@ -192,6 +208,18 @@ _ao_config_get(void) 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; } @@ -283,6 +311,32 @@ ao_config_frequency_set(void) __reentrant 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 @@ -477,18 +531,73 @@ ao_config_radio_cal_set(void) __reentrant 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); @@ -506,6 +615,7 @@ ao_config_log_set(void) __reentrant ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; _ao_config_edit_finish(); } +#endif } #endif /* HAS_LOG */ @@ -737,6 +847,30 @@ ao_config_pyro_time_set(void) } #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; @@ -766,12 +900,20 @@ __code struct ao_config_var ao_config_vars[] = { #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 }, @@ -817,6 +959,10 @@ __code struct ao_config_var ao_config_vars[] = { { "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 }, #if HAS_EEPROM diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index 2b5cd352..164584a5 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -28,6 +28,10 @@ #define USE_EEPROM_CONFIG 0 #endif +#ifndef FLIGHT_LOG_APPEND +#define FLIGHT_LOG_APPEND 0 +#endif + #if USE_STORAGE_CONFIG #include <ao_storage.h> @@ -53,7 +57,7 @@ #endif #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 18 +#define AO_CONFIG_MINOR 21 #define AO_AES_LEN 16 @@ -102,8 +106,21 @@ struct ao_config { #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 @@ -141,6 +158,9 @@ void ao_config_set_radio(void); void +ao_config_log_fix_append(void); + +void ao_config_init(void); #endif /* _AO_CONFIG_H_ */ diff --git a/src/kernel/ao_convert.c b/src/kernel/ao_convert.c index aa9b5f48..db1f2301 100644 --- a/src/kernel/ao_convert.c +++ b/src/kernel/ao_convert.c @@ -19,14 +19,16 @@ #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; @@ -43,9 +45,9 @@ ao_pres_to_altitude(int16_t pres) __reentrant #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; diff --git a/src/kernel/ao_convert_pa.c b/src/kernel/ao_convert_pa.c index fe6e0ef6..410815b6 100644 --- a/src/kernel/ao_convert_pa.c +++ b/src/kernel/ao_convert_pa.c @@ -24,7 +24,11 @@ #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 @@ -35,11 +39,11 @@ static const alt_t altitude_table[] AO_CONST_ATTRIB = { #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; @@ -48,16 +52,16 @@ ao_pa_to_altitude(int32_t pa) 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; @@ -72,7 +76,7 @@ ao_altitude_to_pa(int32_t alt) } 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) diff --git a/src/kernel/ao_convert_pa_test.c b/src/kernel/ao_convert_pa_test.c index 7d5b1922..95422862 100644 --- a/src/kernel/ao_convert_pa_test.c +++ b/src/kernel/ao_convert_pa_test.c @@ -18,6 +18,7 @@ #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" diff --git a/src/kernel/ao_data.h b/src/kernel/ao_data.h index c4b062fd..8f75ad87 100644 --- a/src/kernel/ao_data.h +++ b/src/kernel/ao_data.h @@ -117,9 +117,7 @@ extern volatile __data uint8_t ao_data_count; typedef int32_t pres_t; -#ifndef AO_ALT_TYPE #define AO_ALT_TYPE int32_t -#endif typedef AO_ALT_TYPE alt_t; @@ -146,10 +144,6 @@ typedef int16_t alt_t; #endif -#if !HAS_BARO -typedef int16_t alt_t; -#endif - /* * Need a few macros to pull data from the sensors: * diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c index 2b433ee9..251dbc02 100644 --- a/src/kernel/ao_flight.c +++ b/src/kernel/ao_flight.c @@ -60,10 +60,10 @@ __xdata uint8_t ao_sensor_errors; * 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; @@ -398,14 +398,14 @@ ao_flight(void) } #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 diff --git a/src/kernel/ao_forward.c b/src/kernel/ao_forward.c new file mode 100644 index 00000000..2a937183 --- /dev/null +++ b/src/kernel/ao_forward.c @@ -0,0 +1,48 @@ +/* + * 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"); +} diff --git a/src/kernel/ao_forward.h b/src/kernel/ao_forward.h new file mode 100644 index 00000000..1897dc08 --- /dev/null +++ b/src/kernel/ao_forward.h @@ -0,0 +1,24 @@ +/* + * 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_ */ diff --git a/src/kernel/ao_gps_print.c b/src/kernel/ao_gps_print.c index 47c945d7..d26021da 100644 --- a/src/kernel/ao_gps_print.c +++ b/src/kernel/ao_gps_print.c @@ -20,6 +20,10 @@ #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 { @@ -42,7 +46,7 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant AO_TELEM_GPS_ALTITUDE " %d ", (long) gps_data->latitude, (long) gps_data->longitude, - gps_data->altitude); + AO_TELEMETRY_LOCATION_ALTITUDE(gps_data)); if (gps_data->flags & AO_GPS_DATE_VALID) printf(AO_TELEM_GPS_YEAR " %d " diff --git a/src/kernel/ao_gps_report.c b/src/kernel/ao_gps_report.c index 07201ac2..7ef98a97 100644 --- a/src/kernel/ao_gps_report.c +++ b/src/kernel/ao_gps_report.c @@ -52,8 +52,12 @@ ao_gps_report(void) 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; diff --git a/src/kernel/ao_gps_report_mega.c b/src/kernel/ao_gps_report_mega.c index cb0c0fd9..f3711fb1 100644 --- a/src/kernel/ao_gps_report_mega.c +++ b/src/kernel/ao_gps_report_mega.c @@ -78,7 +78,8 @@ ao_gps_report_mega(void) #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)) { @@ -87,8 +88,8 @@ ao_gps_report_mega(void) 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; diff --git a/src/kernel/ao_gps_report_metrum.c b/src/kernel/ao_gps_report_metrum.c index 696a833b..8ce074fe 100644 --- a/src/kernel/ao_gps_report_metrum.c +++ b/src/kernel/ao_gps_report_metrum.c @@ -44,7 +44,8 @@ ao_gps_report_metrum(void) 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; @@ -55,6 +56,7 @@ ao_gps_report_metrum(void) 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); } diff --git a/src/kernel/ao_gps_show.c b/src/kernel/ao_gps_show.c index 3a05e35a..e45cd795 100644 --- a/src/kernel/ao_gps_show.c +++ b/src/kernel/ao_gps_show.c @@ -19,6 +19,8 @@ #include <ao.h> #endif +#include <ao_data.h> + void ao_gps_show(void) __reentrant { @@ -27,7 +29,11 @@ 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++) diff --git a/src/kernel/ao_kalman.c b/src/kernel/ao_kalman.c index 9aea1f14..7b0f8145 100644 --- a/src/kernel/ao_kalman.c +++ b/src/kernel/ao_kalman.c @@ -23,32 +23,31 @@ #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 @@ -56,40 +55,40 @@ ao_kalman_predict(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) @@ -123,7 +122,7 @@ ao_kalman_err_height(void) #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", @@ -142,21 +141,21 @@ ao_kalman_correct_baro(void) 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 @@ -164,7 +163,7 @@ ao_kalman_correct_baro(void) 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; @@ -187,18 +186,18 @@ ao_kalman_correct_both(void) (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) { @@ -208,18 +207,18 @@ ao_kalman_correct_both(void) (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) { @@ -228,19 +227,19 @@ ao_kalman_correct_both(void) (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 @@ -251,14 +250,14 @@ ao_kalman_correct_accel(void) 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 */ diff --git a/src/kernel/ao_log.c b/src/kernel/ao_log.c index 91617d93..40a96ef7 100644 --- a/src/kernel/ao_log.c +++ b/src/kernel/ao_log.c @@ -142,19 +142,39 @@ ao_log_max_flight(void) 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 @@ -170,6 +190,80 @@ ao_log_scan(void) __reentrant } 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 @@ -190,8 +284,9 @@ ao_log_scan(void) __reentrant if (++log_slot >= log_slots) log_slot = 0; } while (log_slot != log_want); - ao_wakeup(&ao_flight_number); + return 0; +#endif } void @@ -254,7 +349,6 @@ ao_log_delete(void) __reentrant { uint8_t slot; uint8_t slots; - uint32_t log_current_pos, log_end_pos; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) @@ -268,28 +362,7 @@ ao_log_delete(void) __reentrant #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 diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index 33cda3eb..c13a2580 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -51,11 +51,16 @@ extern __pdata enum ao_flight_state ao_log_state; #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); @@ -67,7 +72,7 @@ ao_log(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 */ @@ -176,8 +181,8 @@ struct ao_log_record { 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; @@ -246,7 +251,7 @@ struct ao_log_mega { 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 */ @@ -261,7 +266,8 @@ struct ao_log_mega { 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 */ @@ -273,6 +279,11 @@ struct ao_log_mega { } 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 */ @@ -306,8 +317,9 @@ struct ao_log_metrum { 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 */ @@ -317,7 +329,7 @@ struct ao_log_metrum { 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 { @@ -381,7 +393,7 @@ struct ao_log_gps { 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 */ @@ -396,7 +408,7 @@ struct ao_log_gps { 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 { diff --git a/src/kernel/ao_log_gps.c b/src/kernel/ao_log_gps.c index 3b728c25..7643091c 100644 --- a/src/kernel/ao_log_gps.c +++ b/src/kernel/ao_log_gps.c @@ -26,6 +26,7 @@ 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 @@ -75,7 +76,8 @@ ao_log_gps_data(uint16_t tick, struct ao_telemetry_location *gps_data) 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; @@ -135,3 +137,16 @@ ao_log_flight(uint8_t slot) 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; +} diff --git a/src/kernel/ao_log_gps.h b/src/kernel/ao_log_gps.h index 5851f4d1..a9e8c831 100644 --- a/src/kernel/ao_log_gps.h +++ b/src/kernel/ao_log_gps.h @@ -21,9 +21,6 @@ #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); diff --git a/src/kernel/ao_log_micro.c b/src/kernel/ao_log_micro.c index d665efb5..aef78def 100644 --- a/src/kernel/ao_log_micro.c +++ b/src/kernel/ao_log_micro.c @@ -22,10 +22,17 @@ 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)); @@ -99,8 +106,12 @@ ao_log_micro_dump(void) 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'); diff --git a/src/kernel/ao_microflight.c b/src/kernel/ao_microflight.c index f680e400..f7521f21 100644 --- a/src/kernel/ao_microflight.c +++ b/src/kernel/ao_microflight.c @@ -43,10 +43,12 @@ void 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; @@ -60,19 +62,25 @@ ao_microflight(void) 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) @@ -82,6 +90,9 @@ ao_microflight(void) pa_ground = pa_sum >> GROUND_AVG_SHIFT; pa_sum = 0; sample_count = 0; +#if !BOOST_DETECT + break; +#endif } } @@ -93,7 +104,10 @@ ao_microflight(void) } /* 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(); } @@ -101,6 +115,7 @@ ao_microflight(void) /* 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; @@ -112,8 +127,11 @@ ao_microflight(void) 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) diff --git a/src/kernel/ao_microkalman.c b/src/kernel/ao_microkalman.c index 0684ea2b..75a29cc4 100644 --- a/src/kernel/ao_microkalman.c +++ b/src/kernel/ao_microkalman.c @@ -22,19 +22,19 @@ #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 */ @@ -49,7 +49,7 @@ ao_microkalman_init(void) { ao_pa = pa; ao_k_pa = pa << 8; -} +} void ao_microkalman_predict(void) diff --git a/src/kernel/ao_monitor.c b/src/kernel/ao_monitor.c index 18f170b4..2d75c41c 100644 --- a/src/kernel/ao_monitor.c +++ b/src/kernel/ao_monitor.c @@ -115,6 +115,8 @@ ao_monitor_put(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; @@ -240,7 +242,7 @@ ao_monitor_put(void) 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); } diff --git a/src/kernel/ao_mutex.c b/src/kernel/ao_mutex.c index 952ff462..a36fe939 100644 --- a/src/kernel/ao_mutex.c +++ b/src/kernel/ao_mutex.c @@ -17,6 +17,29 @@ #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 { diff --git a/src/kernel/ao_pyro.c b/src/kernel/ao_pyro.c index 85d88d98..3044d565 100644 --- a/src/kernel/ao_pyro.c +++ b/src/kernel/ao_pyro.c @@ -69,6 +69,16 @@ ao_pyro_print_status(void) 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 @@ -88,63 +98,73 @@ ao_pyro_ready(struct ao_pyro *pyro) 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: @@ -154,10 +174,12 @@ ao_pyro_ready(struct ao_pyro *pyro) 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: @@ -230,7 +252,7 @@ ao_pyro_check(void) 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]; @@ -266,6 +288,16 @@ ao_pyro_check(void) * 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; } @@ -443,7 +475,7 @@ ao_pyro_set(void) 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') @@ -467,13 +499,26 @@ ao_pyro_set(void) } 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(); diff --git a/src/kernel/ao_pyro.h b/src/kernel/ao_pyro.h index b37aaeb1..0fde725a 100644 --- a/src/kernel/ao_pyro.h +++ b/src/kernel/ao_pyro.h @@ -83,6 +83,9 @@ ao_pyro_init(void); void ao_pyro_manual(uint8_t p); +enum ao_igniter_status +ao_pyro_status(uint8_t p); + void ao_pyro_print_status(void); diff --git a/src/kernel/ao_report.c b/src/kernel/ao_report.c index f2263154..5314fc8f 100644 --- a/src/kernel/ao_report.c +++ b/src/kernel/ao_report.c @@ -211,12 +211,23 @@ ao_report_continuity(void) __reentrant 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)); diff --git a/src/kernel/ao_rssi.c b/src/kernel/ao_rssi.c index 244a84fe..793b190b 100644 --- a/src/kernel/ao_rssi.c +++ b/src/kernel/ao_rssi.c @@ -17,9 +17,9 @@ #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) @@ -33,7 +33,7 @@ ao_rssi(void) } void -ao_rssi_set(int rssi_value) +ao_rssi_set(int16_t rssi_value) { if (rssi_value > 0) rssi_value = 0; @@ -45,7 +45,7 @@ ao_rssi_set(int rssi_value) __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; diff --git a/src/kernel/ao_sample.c b/src/kernel/ao_sample.c index 34658951..29bf2bf6 100644 --- a/src/kernel/ao_sample.c +++ b/src/kernel/ao_sample.c @@ -245,7 +245,7 @@ ao_sample_preflight(void) } 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; diff --git a/src/kernel/ao_sample.h b/src/kernel/ao_sample.h index 16d4c507..2ec998bd 100644 --- a/src/kernel/ao_sample.h +++ b/src/kernel/ao_sample.h @@ -24,6 +24,24 @@ * 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 * @@ -87,9 +105,9 @@ * 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 */ @@ -134,21 +152,33 @@ uint8_t ao_sample(void); * 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); diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 9f778b09..56bd715e 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -1,5 +1,5 @@ /* - * 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 @@ -25,6 +25,10 @@ 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; @@ -64,7 +68,7 @@ static void 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; @@ -106,12 +110,13 @@ ao_send_sensor(void) #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; @@ -240,7 +245,7 @@ static void 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; @@ -339,7 +344,7 @@ ao_send_location(void) 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)); @@ -490,12 +495,33 @@ ao_telemetry(void) } } +#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; @@ -521,7 +547,7 @@ ao_telemetry_set_interval(uint16_t interval) 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++; diff --git a/src/kernel/ao_telemetry.h b/src/kernel/ao_telemetry.h index be7d0340..83d432cf 100644 --- a/src/kernel/ao_telemetry.h +++ b/src/kernel/ao_telemetry.h @@ -86,12 +86,9 @@ struct ao_telemetry_configuration { #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 */ @@ -99,7 +96,7 @@ struct ao_telemetry_location { 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) */ @@ -115,10 +112,31 @@ struct ao_telemetry_location { uint16_t ground_speed; /* 26 cm/s */ int16_t climb_rate; /* 28 cm/s */ uint8_t course; /* 30 degrees / 2 */ - uint8_t unused; /* 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 { diff --git a/src/kernel/ao_tracker.c b/src/kernel/ao_tracker.c index 9febc7f0..9b007af8 100644 --- a/src/kernel/ao_tracker.c +++ b/src/kernel/ao_tracker.c @@ -36,9 +36,9 @@ ao_usb_connected(void) #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 @@ -72,7 +72,7 @@ ao_tracker(void) #if !HAS_USB_CONNECT ao_tracker_force_telem = 1; #endif - ao_log_scan(); + log_started = ao_log_scan(); ao_rdf_set(1); @@ -122,12 +122,13 @@ ao_tracker(void) { 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; @@ -153,7 +154,7 @@ ao_tracker(void) 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); } @@ -180,8 +181,7 @@ void ao_tracker_erase_end(void) { if (erasing_current) { - ao_log_scan(); - log_started = 0; + log_started = ao_log_scan(); ao_mutex_put(&tracker_mutex); } } @@ -203,7 +203,7 @@ ao_tracker_set_telem(void) 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); diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 0891903e..21a7a8e5 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -161,16 +161,17 @@ static inline void ao_arch_restore_stack(void) { #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) /* diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index ade8e496..bbe2ea58 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -53,6 +53,7 @@ ALTOS_SRC = \ ao_rssi.c \ ao_send_packet.c \ ao_packet_master.c \ + ao_eeprom_stm.c \ ao_packet.c PRODUCT=MegaDongle-v0.1 diff --git a/src/megadongle-v0.1/ao_megadongle.c b/src/megadongle-v0.1/ao_megadongle.c index 2792af22..68d6de60 100644 --- a/src/megadongle-v0.1/ao_megadongle.c +++ b/src/megadongle-v0.1/ao_megadongle.c @@ -24,7 +24,7 @@ int main(void) { ao_clock_init(); - + #if HAS_STACK_GUARD ao_mpu_init(); #endif @@ -48,7 +48,7 @@ main(void) ao_send_packet_init(); ao_config_init(); - + ao_start_scheduler(); return 0; } diff --git a/src/megadongle-v0.1/ao_pins.h b/src/megadongle-v0.1/ao_pins.h index d460a490..9edd91f4 100644 --- a/src/megadongle-v0.1/ao_pins.h +++ b/src/megadongle-v0.1/ao_pins.h @@ -15,6 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +/* Using TeleMetrum v1.9 board */ + #ifndef _AO_PINS_H_ #define _AO_PINS_H_ @@ -46,7 +48,7 @@ #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 @@ -56,19 +58,18 @@ #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 */ @@ -76,7 +77,7 @@ #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 @@ -85,27 +86,17 @@ #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) @@ -134,15 +125,15 @@ #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 diff --git a/src/microkite/.gitignore b/src/microkite/.gitignore new file mode 100644 index 00000000..7a5d0a1f --- /dev/null +++ b/src/microkite/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +microkite-* diff --git a/src/microkite/Makefile b/src/microkite/Makefile new file mode 100644 index 00000000..b7523758 --- /dev/null +++ b/src/microkite/Makefile @@ -0,0 +1,134 @@ +# +# 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) diff --git a/src/microkite/ao_pins.h b/src/microkite/ao_pins.h new file mode 100644 index 00000000..346b63a1 --- /dev/null +++ b/src/microkite/ao_pins.h @@ -0,0 +1,71 @@ +/* + * 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_ */ diff --git a/src/microkite/microkite-load.tmpl b/src/microkite/microkite-load.tmpl new file mode 100644 index 00000000..08236a15 --- /dev/null +++ b/src/microkite/microkite-load.tmpl @@ -0,0 +1,20 @@ +#!/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} diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 6ae3d0be..ac00f635 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -8,8 +8,15 @@ vpath make-altitude-pa ../util 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 @@ -55,8 +62,6 @@ CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTIN NICKLE=nickle -PROG=micropeak-v0.1 - SRC=$(ALTOS_SRC) OBJ=$(SRC:.c=.o) @@ -68,7 +73,7 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: $(PROG) $(PROG).hex +all: $(PROG) $(HEX) micropeak-load CHECK=sh ../util/check-avr-mem @@ -76,16 +81,16 @@ $(PROG): Makefile $(OBJ) $(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) > $@ @@ -98,22 +103,30 @@ ao_product.o: ao_product.c ao_product.h 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: diff --git a/src/micropeak/micropeak-load.tmpl b/src/micropeak/micropeak-load.tmpl new file mode 100644 index 00000000..08236a15 --- /dev/null +++ b/src/micropeak/micropeak-load.tmpl @@ -0,0 +1,20 @@ +#!/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} diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 81151364..b7c28987 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -83,7 +83,7 @@ quiet ?= $($1) 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 diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 90fe7833..7311c21e 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -85,7 +85,7 @@ quiet ?= $($1) 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 diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index dbbf57d8..e9b144c0 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -24,6 +24,7 @@ INC = \ altitude.h \ ao_kalman.h \ ao_product.h \ + ao_telemetry.h \ $(TM_INC) CORE_SRC = \ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index d2fcb6d8..e1e350a6 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -85,7 +85,7 @@ quiet ?= $($1) 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 diff --git a/src/product/ao_micropeak.c b/src/product/ao_micropeak.c index 10f0d192..54522d86 100644 --- a/src/product/ao_micropeak.c +++ b/src/product/ao_micropeak.c @@ -73,8 +73,9 @@ main(void) ao_report_altitude(); ao_pips(); ao_log_micro_dump(); - +#if BOOST_DELAY ao_delay(BOOST_DELAY); +#endif ao_microflight(); diff --git a/src/product/ao_micropeak.h b/src/product/ao_micropeak.h index 0ec407d7..622f5a69 100644 --- a/src/product/ao_micropeak.h +++ b/src/product/ao_micropeak.h @@ -29,8 +29,21 @@ #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 */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index b461cd3f..7ad3b4b8 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -64,6 +64,9 @@ #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); @@ -77,6 +80,9 @@ void ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); void +ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index); + +void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void @@ -95,6 +101,15 @@ ao_spi_init(void); 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); \ @@ -252,6 +267,8 @@ extern struct ao_stm_usart ao_stm_usart3; #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; @@ -369,10 +386,10 @@ static inline void ao_arch_start_scheduler(void) { 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_ */ diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 56329c24..885af544 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -154,6 +154,28 @@ 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) +{ + 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) { struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; @@ -356,13 +378,11 @@ ao_spi_enable_index(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 */ @@ -378,7 +398,7 @@ ao_spi_get(uint8_t spi_index, uint32_t speed) (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]); @@ -386,13 +406,32 @@ ao_spi_get(uint8_t spi_index, uint32_t speed) /* 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) { diff --git a/src/telebt-v1.0/ao_pins.h b/src/telebt-v1.0/ao_pins.h index 9e47f3b8..4181ef35 100644 --- a/src/telebt-v1.0/ao_pins.h +++ b/src/telebt-v1.0/ao_pins.h @@ -48,6 +48,8 @@ #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 diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile index 25267268..99d29826 100644 --- a/src/telefire-v0.1/Makefile +++ b/src/telefire-v0.1/Makefile @@ -25,7 +25,6 @@ INC = \ CORE_SRC = \ ao_cmd.c \ ao_config.c \ - ao_convert.c \ ao_mutex.c \ ao_panic.c \ ao_stdio.c \ diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index f7a3ff2c..47ae663f 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -18,7 +18,8 @@ #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 diff --git a/src/telefire-v0.2/Makefile b/src/telefire-v0.2/Makefile index ad5065c1..944543c5 100644 --- a/src/telefire-v0.2/Makefile +++ b/src/telefire-v0.2/Makefile @@ -25,7 +25,6 @@ INC = \ CORE_SRC = \ ao_cmd.c \ ao_config.c \ - ao_convert.c \ ao_mutex.c \ ao_panic.c \ ao_stdio.c \ diff --git a/src/telefire-v0.2/ao_pins.h b/src/telefire-v0.2/ao_pins.h index 96e6b066..28cc65b9 100644 --- a/src/telefire-v0.2/ao_pins.h +++ b/src/telefire-v0.2/ao_pins.h @@ -18,7 +18,9 @@ #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 @@ -95,11 +97,13 @@ #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 diff --git a/src/telegps-v1.0/ao_pins.h b/src/telegps-v1.0/ao_pins.h index 5f53dd9d..d2382a56 100644 --- a/src/telegps-v1.0/ao_pins.h +++ b/src/telegps-v1.0/ao_pins.h @@ -71,11 +71,11 @@ #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 diff --git a/src/telelco-v0.2/ao_lco.c b/src/telelco-v0.2/ao_lco.c index b3f5bb16..4b5f7a9b 100644 --- a/src/telelco-v0.2/ao_lco.c +++ b/src/telelco-v0.2/ao_lco.c @@ -258,7 +258,7 @@ ao_lco_search(void) 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); diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h index a6fd4ff8..da790b14 100644 --- a/src/telelco-v0.2/ao_pins.h +++ b/src/telelco-v0.2/ao_pins.h @@ -48,6 +48,7 @@ #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 diff --git a/src/telemega-v1.0/Makefile b/src/telemega-v1.0/Makefile index 46c768e4..4a1b3908 100644 --- a/src/telemega-v1.0/Makefile +++ b/src/telemega-v1.0/Makefile @@ -31,6 +31,7 @@ INC = \ ao_mpu.h \ stm32l.h \ math.h \ + ao_ms5607_convert.c \ Makefile # diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile index ca69dc41..8657e9a9 100644 --- a/src/telemini-v2.0/Makefile +++ b/src/telemini-v2.0/Makefile @@ -25,7 +25,8 @@ INC = \ ao_int64.h \ ao_sample.h \ ao_exti.h \ - ao_task.h + ao_task.h \ + altitude-pa-small.h CORE_SRC = \ ao_cmd.c \ diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index f202ccd1..ed911798 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -22,15 +22,18 @@ #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 @@ -39,6 +42,8 @@ #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 diff --git a/src/telerepeat-v1.0/Makefile b/src/telerepeat-v1.0/Makefile new file mode 100644 index 00000000..17f68377 --- /dev/null +++ b/src/telerepeat-v1.0/Makefile @@ -0,0 +1,100 @@ +# +# 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: diff --git a/src/telerepeat-v1.0/ao_pins.h b/src/telerepeat-v1.0/ao_pins.h new file mode 100644 index 00000000..2a7dbd3b --- /dev/null +++ b/src/telerepeat-v1.0/ao_pins.h @@ -0,0 +1,111 @@ +/* + * 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_ */ diff --git a/src/telerepeat-v1.0/ao_telerepeat.c b/src/telerepeat-v1.0/ao_telerepeat.c new file mode 100644 index 00000000..21bf8a73 --- /dev/null +++ b/src/telerepeat-v1.0/ao_telerepeat.c @@ -0,0 +1,47 @@ +/* + * 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(); +} diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index 30239afc..68bb44ee 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -62,6 +62,7 @@ #define HAS_RSSI 0 #define HAS_AES 0 #define HAS_RADIO 1 + #define HAS_TELEMETRY 0 #endif #if DBG_ON_P1 diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 1c12c437..472af534 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -71,7 +71,9 @@ #define HAS_P2_ISR 1 #define BATTERY_PIN 5 - + #define HAS_TELEMETRY 0 + + #define AO_VALUE_32 0 #endif #if DBG_ON_P1 diff --git a/src/test/Makefile b/src/test/Makefile index 017f7f71..02e1d22b 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,7 @@ 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 @@ -33,6 +34,9 @@ ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kal 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 $@ $< diff --git a/src/test/ao_aprs_test.c b/src/test/ao_aprs_test.c index 86cf527a..ae505dea 100644 --- a/src/test/ao_aprs_test.c +++ b/src/test/ao_aprs_test.c @@ -21,6 +21,8 @@ #include <stdint.h> #include <stdarg.h> +#define HAS_GPS 1 + #include <ao_telemetry.h> #define AO_GPS_NUM_SAT_MASK (0xf << 0) @@ -97,41 +99,14 @@ audio_gap(int secs) #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 */ diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 0647fc6c..8b737ca1 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -34,15 +34,21 @@ #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 @@ -50,6 +56,7 @@ int ao_gps_new; #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]; @@ -57,7 +64,25 @@ struct ao_adc { 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 */ @@ -92,6 +117,7 @@ struct ao_adc { #include <ao_data.h> #include <ao_log.h> #include <ao_telemetry.h> +#include <ao_sample.h> #if TELEMEGA int ao_gps_count; @@ -174,7 +200,7 @@ ao_gps_angle(void) 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; @@ -185,17 +211,6 @@ ao_gps_angle(void) #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; @@ -233,7 +248,7 @@ double main_time; int tick_offset; -static int32_t ao_k_height; +static ao_k_t ao_k_height; int16_t ao_time(void) @@ -305,7 +320,7 @@ struct ao_cmds { #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; @@ -455,7 +470,7 @@ ao_insert(void) #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); @@ -550,6 +565,7 @@ ao_insert(void) 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], @@ -559,6 +575,7 @@ ao_insert(void) (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], @@ -581,9 +598,9 @@ ao_insert(void) #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 @@ -591,7 +608,7 @@ ao_insert(void) time, height, accel, -#if TELEMEGA +#if TELEMEGA && 0 ao_sample_orient, ao_mpu6000_accel(ao_data_static.mpu6000.accel_x), @@ -674,7 +691,8 @@ ao_sleep(void *wchan) { #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(); @@ -755,7 +773,10 @@ ao_sleep(void *wchan) 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; @@ -795,11 +816,64 @@ ao_sleep(void *wchan) 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); @@ -924,7 +998,7 @@ ao_sleep(void *wchan) if (type != 'F' && !ao_flight_started) continue; -#if TELEMEGA +#if TELEMEGA || TELEMETRUM_V2 (void) a; (void) b; #else @@ -945,8 +1019,6 @@ ao_sleep(void *wchan) 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(); diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index e799ab0f..543bbcc3 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -53,6 +53,9 @@ struct ao_gps_orig { 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) @@ -433,7 +436,7 @@ ao_dump_state(void *wchan) if (wchan != &ao_gps_new) return; - + if (ao_gps_new & AO_GPS_NEW_DATA) { ao_gps_print(&ao_gps_data); putchar('\n'); diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 1b590d5e..5eb7118d 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -16,6 +16,7 @@ */ #define AO_GPS_TEST +#define HAS_GPS 1 #include "ao_host.h" #include <termios.h> #include <errno.h> @@ -53,6 +54,9 @@ struct ao_gps_orig { 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) diff --git a/src/test/ao_gps_test_ublox.c b/src/test/ao_gps_test_ublox.c index 4eb4b837..5ea205d6 100644 --- a/src/test/ao_gps_test_ublox.c +++ b/src/test/ao_gps_test_ublox.c @@ -16,6 +16,7 @@ */ #define AO_GPS_TEST +#define HAS_GPS 1 #include "ao_host.h" #include <termios.h> #include <errno.h> @@ -44,7 +45,7 @@ struct ao_telemetry_location { 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 */ @@ -53,8 +54,14 @@ struct ao_telemetry_location { 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) diff --git a/src/test/ao_micropeak_test.c b/src/test/ao_micropeak_test.c index 5961bd93..f4af707e 100644 --- a/src/test/ao_micropeak_test.c +++ b/src/test/ao_micropeak_test.c @@ -33,6 +33,7 @@ uint8_t ao_flight_debug; #define AO_FLIGHT_TEST typedef int32_t alt_t; +typedef int32_t pres_t; #define AO_MS_TO_TICKS(ms) ((ms) / 10) diff --git a/src/test/plottest b/src/test/plottest index 76af5ee7..7d253ff1 100755 --- a/src/test/plottest +++ b/src/test/plottest @@ -10,7 +10,7 @@ plot "$1" using 1:3 with lines axes x1y1 title "raw height",\ "$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 diff --git a/src/util/make-altitude-pa b/src/util/make-altitude-pa index 22831d50..d36f3f41 100644 --- a/src/util/make-altitude-pa +++ b/src/util/make-altitude-pa @@ -185,105 +185,135 @@ line_t best_fit(real[] values, int first, int last) { 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(); diff --git a/telegps/.gitignore b/telegps/.gitignore index edb509f2..1af9e0f1 100644 --- a/telegps/.gitignore +++ b/telegps/.gitignore @@ -17,7 +17,7 @@ TeleGPS-Linux-*.tar.bz2 TeleGPS-Linux-*.sh TeleGPS-Mac-*.zip TeleGPS-Windows-*.exe -telegps.desktop +*.desktop telegps-windows.log *.dll *.dylib diff --git a/telegps/Info.plist.in b/telegps/Info.plist.in index df05bb6e..89870a8c 100644 --- a/telegps/Info.plist.in +++ b/telegps/Info.plist.in @@ -23,7 +23,34 @@ <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> diff --git a/telegps/Makefile.am b/telegps/Makefile.am index 7b550e9e..3b33428e 100644 --- a/telegps/Makefile.am +++ b/telegps/Makefile.am @@ -58,23 +58,42 @@ ALTOSUILIB_CLASS=\ 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 @@ -89,7 +108,7 @@ FIRMWARE_TG=$(FIRMWARE_TG_1_0) 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) @@ -101,12 +120,12 @@ clean-local: $(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 @@ -120,15 +139,15 @@ DOC=$(TELEGPS_DOC) 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 @@ -194,8 +213,6 @@ $(FATJAR): classtelegps.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CL -C classes org \ -C ../libaltos libaltosJNI -classaltosui.stamp: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) - libaltos.so: build-libaltos -rm -f "$@" $(LN_S) ../libaltos/.libs/"$@" . @@ -269,7 +286,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile 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 diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index 6e68dd30..a4b221e8 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -23,8 +23,8 @@ import javax.swing.*; 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 @@ -32,12 +32,12 @@ public class TeleGPS { 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); } @@ -58,8 +58,10 @@ public class TeleGPS JMenu file_menu; JMenu monitor_menu; JMenu device_menu; - AltosFreqList frequencies; + AltosUIFreqList frequencies; ActionListener frequency_listener; + AltosUIRateList rates; + ActionListener rate_listener; Container bag; @@ -184,6 +186,7 @@ public class TeleGPS telegps_status.disable_receive(); disable_frequency_menu(); + disable_rate_menu(); } void connect(AltosDevice device) { @@ -364,6 +367,40 @@ public class TeleGPS } + 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); @@ -374,8 +411,10 @@ public class TeleGPS 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; @@ -409,16 +448,38 @@ public class TeleGPS 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(); @@ -434,9 +495,26 @@ public class TeleGPS 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>(); diff --git a/telegps/TeleGPSConfig.java b/telegps/TeleGPSConfig.java index 3505b0bb..e607a5a5 100644 --- a/telegps/TeleGPSConfig.java +++ b/telegps/TeleGPSConfig.java @@ -22,8 +22,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.text.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class TeleGPSConfig implements ActionListener { diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java index 5f269fd3..7a59bf48 100644 --- a/telegps/TeleGPSConfigUI.java +++ b/telegps/TeleGPSConfigUI.java @@ -21,8 +21,8 @@ import java.awt.*; 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 @@ -37,7 +37,9 @@ public class TeleGPSConfigUI 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; @@ -49,10 +51,12 @@ public class TeleGPSConfigUI 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; @@ -72,6 +76,10 @@ public class TeleGPSConfigUI "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", @@ -141,6 +149,13 @@ public class TeleGPSConfigUI 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"); @@ -148,6 +163,15 @@ public class TeleGPSConfigUI 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)"); @@ -255,7 +279,7 @@ public class TeleGPSConfigUI 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"); @@ -311,6 +335,31 @@ public class TeleGPSConfigUI 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; @@ -337,6 +386,33 @@ public class TeleGPSConfigUI 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; @@ -566,12 +642,16 @@ public class TeleGPSConfigUI } 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 */ @@ -590,6 +670,9 @@ public class TeleGPSConfigUI serial_value.setText(String.format("%d", serial)); } + public void set_altitude_32(int altitude_32) { + } + public void set_main_deploy(int new_main_deploy) { } @@ -657,6 +740,14 @@ public class TeleGPSConfigUI 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); @@ -748,7 +839,12 @@ public class TeleGPSConfigUI } 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 { @@ -756,7 +852,12 @@ public class TeleGPSConfigUI } 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 { @@ -782,4 +883,15 @@ public class TeleGPSConfigUI 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; + } } diff --git a/telegps/TeleGPSDisplayThread.java b/telegps/TeleGPSDisplayThread.java index a3d4ea07..18b8d9fc 100644 --- a/telegps/TeleGPSDisplayThread.java +++ b/telegps/TeleGPSDisplayThread.java @@ -21,8 +21,8 @@ import java.awt.*; import javax.swing.*; import java.io.*; import java.text.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class TeleGPSDisplayThread extends Thread { diff --git a/telegps/TeleGPSGraphUI.java b/telegps/TeleGPSGraphUI.java index 244eb7b9..b59b122c 100644 --- a/telegps/TeleGPSGraphUI.java +++ b/telegps/TeleGPSGraphUI.java @@ -26,8 +26,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_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; diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java index e87fea90..1b4751b9 100644 --- a/telegps/TeleGPSInfo.java +++ b/telegps/TeleGPSInfo.java @@ -21,8 +21,8 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class TeleGPSInfo extends AltosUIFlightTab { diff --git a/telegps/TeleGPSPreferences.java b/telegps/TeleGPSPreferences.java index 8bd371f4..2738ceea 100644 --- a/telegps/TeleGPSPreferences.java +++ b/telegps/TeleGPSPreferences.java @@ -22,7 +22,7 @@ import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altosuilib_3.*; public class TeleGPSPreferences extends AltosUIConfigure diff --git a/telegps/TeleGPSState.java b/telegps/TeleGPSState.java index a76182ed..27321c73 100644 --- a/telegps/TeleGPSState.java +++ b/telegps/TeleGPSState.java @@ -21,8 +21,8 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; +import org.altusmetrum.altoslib_5.*; +import org.altusmetrum.altosuilib_3.*; public class TeleGPSState extends AltosUIFlightTab { diff --git a/telegps/TeleGPSStatus.java b/telegps/TeleGPSStatus.java index f3951a37..1d4415d6 100644 --- a/telegps/TeleGPSStatus.java +++ b/telegps/TeleGPSStatus.java @@ -19,8 +19,8 @@ package org.altusmetrum.telegps; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_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; diff --git a/telegps/TeleGPSStatusUpdate.java b/telegps/TeleGPSStatusUpdate.java index e7684d88..3d2b7f34 100644 --- a/telegps/TeleGPSStatusUpdate.java +++ b/telegps/TeleGPSStatusUpdate.java @@ -18,7 +18,7 @@ package org.altusmetrum.telegps; import java.awt.event.*; -import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altoslib_5.*; public class TeleGPSStatusUpdate implements ActionListener { diff --git a/telegps/telegps.desktop.in b/telegps/altusmetrum-telegps.desktop.in index 3d249d8a..7a1b3536 100644 --- a/telegps/telegps.desktop.in +++ b/telegps/altusmetrum-telegps.desktop.in @@ -3,8 +3,8 @@ Type=Application Name=TeleGPS GenericName=TeleGPS monitor, download and analysis Comment=View and log data from TeleGPS tracking devices -Icon=%icondir%/telegps.svg +Icon=%icondir%/altusmetrum-telegps.svg Exec=%bindir%/telegps %f Terminal=false -MimeType=text/plain; +MimeType=application/vnd.altusmetrum.telemetry;application/vnd.altusmetrum.eeprom Categories=Education;Electronics;Science; diff --git a/telegps/telegps-windows.nsi.in b/telegps/telegps-windows.nsi.in index b4145520..603d4971 100644 --- a/telegps/telegps-windows.nsi.in +++ b/telegps/telegps-windows.nsi.in @@ -2,14 +2,24 @@ !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" @@ -19,7 +29,7 @@ RequestExecutionLevel admin ShowInstDetails Show -ComponentText "TeleGPS Software Installer" +ComponentText "${REG_NAME} Software and Driver Installer" Function .onInit DetailPrint "Checking host operating system" @@ -31,6 +41,16 @@ Function .onInit ${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 @@ -66,12 +86,12 @@ done: 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" @@ -86,13 +106,13 @@ Section "TeleGPS Application" 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" @@ -114,38 +134,105 @@ Section "Documentation" 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 |