--- /dev/null
+ao-tools/libaltos/altos.dll export-ignore
+ao-tools/libaltos/libaltos.dylib export-ignore
.deps
TAGS
aclocal.m4
+libtool
+ltmain.sh
+src/Version
src/ao_flight_test
src/ao_gps_test
src/ao_gps_test_skytraq
+commit 59798c6fd11502a9c8b66090c23ba50eb250692e
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 3 12:43:45 2010 -0700
+
+ altosui: Catch I/O errors on telemetry device, report to user
+
+ This catches the USB device being unplugged and makes sure the
+ user sees an error dialog in this case.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 16d8d6a8853d09f683b13f9cda3c3174a0aab130
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 3 12:31:05 2010 -0700
+
+ altosui: Must flush serial line after configuring for telemetry
+
+ Without flushing the configuration commands to the serial device, it
+ never sees them as the telemetry input thread doesn't flush.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d4f64e95e31e2335470efc15df2ab357b7d197f3
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 3 11:48:55 2010 -0700
+
+ Revert "altosui: Deal with altos bug setting radio channel while monitoring"
+
+ This reverts commit ba65e4aeb952a1cf49a77f1e24e235508fcea71f.
+
+ Testing the old code
+
+commit 71191ecef3ba0e00d0f8a7cd1a24982bfa44ec72
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 3 01:30:33 2010 -0700
+
+ altosui: Allow 'connect to device' when already connected
+
+ Opening another serial device involves shutting down the display
+ thread (to reset its state) and spawning another one. Shutting down
+ the display thread normally closes the serial device as a part of the
+ process, and if this isn't done before the new serial device is
+ opened, then the new serial device ends up getting closed too.
+
+ Interrupting the display thread and waiting for it to stop before
+ opening the new serial device solves the problem.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ba65e4aeb952a1cf49a77f1e24e235508fcea71f
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 3 01:21:57 2010 -0700
+
+ altosui: Deal with altos bug setting radio channel while monitoring
+
+ If the monitoring thread is active, then setting the radio channel can
+ sometimes cause the monitoring thread to get stuck. I'm not entirely
+ sure why though. For now, work around the issue by making sure
+ monitoring is off, and the monitoring thread has stopped, before
+ changing the radio channel.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e5ef42c2b22c6639d90631dbbb588f9fd2494385
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 3 01:12:24 2010 -0700
+
+ altosui: Report telemetry CRC errors in UI
+
+ Telemetry CRC errors can signal problems with TeleMetrum or TeleDongle
+ units, so report them in the UI.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3b3aa448f3a0f44137f7530b04b58967ba5f22f5
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Sep 2 21:11:29 2010 -0700
+
+ altosui: build Mac OS .zip file to include paths
+
+ Without the paths, the OS X zip file doesn't create a usable
+ application structure.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cff0d1ef6b338b3d5ad9450d4d5f95df934cb5e4
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 1 22:56:34 2010 -0700
+
+ altosui: Post error dialog on invalid ROM config values.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8d8980f56a4f2c7d6f2ce667130706e0f04f8ded
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 1 22:56:12 2010 -0700
+
+ altosui: Remove some debug printfs from AltosRomconfig class
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5ee6cd41ed189c3166f76558ecada80917f40652
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 1 22:47:15 2010 -0700
+
+ altosui: Hide internal rom config UI helper function
+
+ This was getting mis-used by the flash UI causing the rom dialog
+ 'cancel' button to work just like 'ok'.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9a690c9795e8257d2a3225f905117681668a472f
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 1 22:46:04 2010 -0700
+
+ altosui: allow flashing to be canceled from the rom config dialog
+
+ Was using the rom config class wrong, causing cancel actions to work
+ just like 'ok' actions. Oops.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2f07ad14a16dbf1b75c71784ceae303825c90ade
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 1 22:43:22 2010 -0700
+
+ altosui: Abort flashing if debug port isn't working
+
+ Check each command going over the debug port and make sure it works as
+ expected. This commit adds checks for initializing the clock,
+ selecting the desired program counter and running the flash
+ program.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cf30343aadd5039627a85319872685f743e64b16
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:55:41 2010 -0400
+
+ update changelogs for Debian build
+
+commit 59a40f6d5a2159b9009a3fa0737bb679efd5b32c
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:55:01 2010 -0400
+
+ another distclean fix
+
+commit 59ff9180f11063c257746b895a167179b3a4ff7c
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:53:16 2010 -0400
+
+ and a few more distclean fixes
+
+commit 3aafd70257b70b7c11ba9c55749157979bc61ea2
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:52:04 2010 -0400
+
+ more makefile distclean target work
+
+commit d5a6ad87c7a9ac03b2e694bed0a54b6cc4322a6f
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:50:16 2010 -0400
+
+ update changelogs for Debian build
+
+commit 14fa24ed93b3b1cec08a170004c6fb7f4d74f7e5
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:48:31 2010 -0400
+
+ update changelogs for Debian build
+
+commit 83552dfa0d38db9cdf3efc89e64e6c7896467856
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:47:54 2010 -0400
+
+ add distclean targets to libaltos and altosui to all Debian package to build
+
+commit 6f24d2a476759104a10b26b54faff2b18b0e208b
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:46:21 2010 -0400
+
+ update changelogs for Debian build
+
+commit d079bfe86ed40ff450ece445cf5f5e3970e44cec
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Sep 2 00:44:30 2010 -0400
+
+ update changelogs for Debian build
+
+commit a470315e5d822a69ef5304512cf73c604c88e481
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 1 20:14:51 2010 -0700
+
+ altosui: Remove Manifest.txt from git repo as it's built now
+
+ This file is built with appropriate contents for each different .jar file.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1177e0a684328422be5adc68093d0091a218a824
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Sep 1 19:53:24 2010 -0700
+
+ altos: Bounds check Skytraq GPS tracking data array
+
+ Missing GPS serial data could cause the tracking array reset to
+ get skipped, causing the array to be overrun, smashing critical data
+ beyond the array.
+
+ This was detected using the 'altosui' flash command to program a
+ device from TM. Hitting the USB that hard caused TM to crash with a
+ mutex error (3 beeps) after the ao_gps_task structure was overwritten
+ with zeros.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 775acb89660cdee2f3c54c38297baefe39f2414c
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 22:24:09 2010 -0700
+
+ altosui: missed AltosReader.class in the Makefile
+
+ This caused clean builds to fail to make this file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bd2b9d958c2b7f846031b076ed51c4fbaaf2d68f
+Author: Bdale Garbee <bdale@gag.com>
+Date: Tue Aug 31 00:20:06 2010 -0400
+
+ update changelogs for Debian build
+
+commit d006c5e1255433181aca4c8e6a277b2d1bc0841b
+Author: Bdale Garbee <bdale@gag.com>
+Date: Tue Aug 31 00:19:37 2010 -0400
+
+ add runtime dependencies for altos binary package
+
+commit c1c7d731e3774883fa0bb5538be225a59334d124
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 30 19:52:51 2010 -0600
+
+ update changelogs for Debian build
+
+commit c35632efb1919764e4b8581ed6fcf2bedd4bd517
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 30 19:37:50 2010 -0600
+
+ update changelogs for Debian build
+
+commit 2a004d17a13b4ff52d892bfdecff8ad3d0823f7c
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 30 19:37:17 2010 -0600
+
+ don't build all the "fat" jar deliverables by default
+
+commit 507e429db6638f82c32449e9c5ca06b46da30134
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 30 19:09:00 2010 -0600
+
+ update changelogs for Debian build
+
+commit 25764fcd1b65c3a5a817afdb5901ac30e8a5f0c0
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 30 19:08:29 2010 -0600
+
+ update changelogs for Debian build
+
+commit 4790f78aead8a816e5b247c022b2998ce3a94053
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 30 18:48:50 2010 -0600
+
+ add a .gitattributes file, configuring the Mac and Windows binary library
+ files with the export-ignore attribute, in hopes that this will prevent
+ them showing up in source packages
+
+commit 81318e5b7179b0311ab099043ecb04a25d763750
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 30 18:15:40 2010 -0600
+
+ make invocation of 'install' pathless to work on more Unix variants
+
+commit cbc72399a0f4d7429df0189bcdae683dd491cb9e
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 30 17:56:56 2010 -0600
+
+ continue even if rm's don't have anything to do
+
+commit a9a8d23c877e6f6c76857b7c85e3d43b4da1db27
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 05:49:11 2010 -0700
+
+ altosui: Devices with USB id 0x000a always get listed
+
+ List 'unknown' AltusMetrum devices anytime the UI needs a device
+ name.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a94900b8862b99b4e317ea0ee3edd2a560f270c7
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 05:48:23 2010 -0700
+
+ altosui: build debian-style altosui too
+
+ This adds the dependencies to make sure altosui and altosui.jar get built.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 38ac388baf8125c0644b868a7aaf8eba1bdf990d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 05:28:37 2010 -0700
+
+ altosui: Build linux, mac and windows archives on Linux
+
+ This adds 'fat' archives for each target OS.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 35d9a8214252dbe79aeb69ae47d2e5c58a654702
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 05:27:45 2010 -0700
+
+ libaltos: Use overlapped I/O on windows
+
+ Otherwise, reads block writes and vice-versa. Crazy stuff.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c7ba92317ac55272acbde12416448ebd17b983a6
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 04:52:00 2010 -0700
+
+ altos: Windows sends USB Out packets of 0 length. Ack them.
+
+ This was an untested case as no other operating system sents 0-length
+ out packets (they're not necessary). The correct response is to ACK
+ them by clearing the OUTPKT_RDY bit so that another packet can be sent.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 20a472cfe3369200150ea4ff067ceb28968dbcac
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 02:58:23 2010 -0700
+
+ libaltos: Add pre-built Windows .dll
+
+ This lets us create the windows distribution on Linux.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0300fe581c949232bc52b05fe9c1f6032cad6b60
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 02:56:25 2010 -0700
+
+ libaltos: Add pre-built Mac OS X libaltos.dylib
+
+ This allows the mac bits to be built on Linux.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5d48c494325524bbeed10e0dc7300ed44e7e208e
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 02:53:26 2010 -0700
+
+ Update telemetrum.inf to include all current USB ids.
+
+ Windows 7 has 'encouraged' us to split out each product into a
+ separate USB ID. telemetrum.inf now has all of them listed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit df34bbe7d1c43b12ab6d610fe810b6e1683e4c21
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 02:49:49 2010 -0700
+
+ libaltos: Improve Makefile
+
+ Builds Windows .dll correctly now and sample app.
+ Moves linux install target to end so it is not default
+ Adds .NOTPARALLEL to disable parallel gnumake.
+ Removes -g debugging flags to shrink file size.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit dd5374b8e660012ae4f8b058454fd101e0749ca7
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 30 02:00:30 2010 -0700
+
+ libaltos: Fix windows build.
+
+ Need stdlib.h to get calloc/free defined, remove debug printfs, fix
+ serial timeouts.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 63c832394a829f41b8f77d075786530536360349
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 23:22:27 2010 -0700
+
+ altos: shut down packet mode cleanly
+
+ Instead of constantly bashing the packet master thread, let it shut
+ itself down in an orderly fashion. It will shut down fairly quickly as
+ all of the activities in that thread are bounded. Otherwise, the
+ master packet thread might leave mutexes locked and all sorts of other
+ horrors.
+
+ Tested on Linux and Mac OS X and shown to be reliable.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 43619c13f749b79c096d1e8fdab3d5cfb5fd85f1
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 22:42:23 2010 -0700
+
+ altos: Abort radio harder when terminating packet mode.
+
+ Make sure the master radio tasks don't get stuck waiting for an
+ incoming packet again by aborting the radio each time we poke the
+ tasks.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c4a8569f61eddf690d00337543462235ecbfbe54
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 22:41:18 2010 -0700
+
+ altos: flush pending output when terminating packet mode
+
+ Just in case the last command sent hasn't been transmitted, hang
+ around for up to a second waiting for the data to get across the link.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1acd3c7ec167b1b18e4ea493e5978c938a91cc89
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 21:45:19 2010 -0700
+
+ libaltos: cjnitest needs altos_flush now
+
+commit 6527357d1f0e94faf9e7dacac10a39875131be7c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 21:43:46 2010 -0700
+
+ libaltos: Missing OS_LDFLAGS on cjnitest build
+
+commit b7fa1ea3338f63b8edcf8aacccb5e519ca0b213f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 21:41:40 2010 -0700
+
+ libaltos: Mac OS X cannot use 'poll(2)' on serial lines.
+
+ Who ships this stuff, anyway? Instead of blocking, we'll poll every 100ms now,
+ otherwise, we won't be able to abort the read when the device is closed. Yay!
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e60c59123232915e808cee23ef89eb1a38ced34b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 21:40:21 2010 -0700
+
+ altosui: discard invalid lines while reading Eeprom flight data
+
+ This shouldn't happen, but it's easy enough to get back in sync by just
+ skipping lines with weird contents.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ae02b1590439d5c8dfb472cf1f83a14fdcfbaf11
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 21:36:47 2010 -0700
+
+ altosui: provide separate flush_input/flush_output for serial. deal with monitor automatically
+
+ (yes, this should be two patches, but the diffs in AltosSerial were merged together).
+
+ First, this replaces the existing flush/flush_reply mess with two simple functions,
+ one to flush output to the serial device, making sure that all data written will be seen
+ while we wait for input. The other sucks any pending input off of the serial line and
+ discards it.
+
+ Second, AltosSerial now tracks whether the serial line is being used for telemetry
+ monitoring. If so, it enables monitoring, otherwise it disables it. Eliminates a
+ bunch of manual state tracking elsewhere.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit edcfb1bdf64772d3b83405ccf99385b8fea5d8e4
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 29 17:33:59 2010 -0700
+
+ libaltos: AltusMetrum devices use more than one USB ID.
+
+ List all usb devices, picking those with AltusMetrum IDs.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 236685807b63860ad033aa0254ce8f6d8d36d4ef
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 22:26:09 2010 -0600
+
+ update changelogs for Debian build
+
+commit 1cda15fdef2d9d3e54354bd5c43a0bcc7e3240cb
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 22:24:51 2010 -0600
+
+ fix up for an 0.7 release
+
+commit 4c5c7c7f198775c398c1ad2edafb3488384cc297
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 22:13:38 2010 -0600
+
+ update changelogs for Debian build
+
+commit 42055af5c6f17d14a2f1c6a2b5e1ce6d3b45a615
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 13:13:19 2010 -0600
+
+ update changelogs for Debian build
+
+commit 0bd4cc03b3bf23aa32b5ce1921078021d1d8a9c6
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 13:12:46 2010 -0600
+
+ fix path to installed shared library
+
+commit 99c1d9b4ef10ec4ebbee058ce0bb38c954a0a3a6
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 12:41:26 2010 -0600
+
+ update changelogs for Debian build
+
+commit cf65c6b8056c4af7c26b52ec6f9fbd3400cef638
+Merge: 5f2f6a8 ae5eff7
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 12:38:25 2010 -0600
+
+ Merge branch 'bdale'
+
+ Conflicts:
+ debian/control
+
+commit ae5eff7bc0b63047737223423009707bedcb00f5
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 12:37:36 2010 -0600
+
+ Revert "lose the prebuild hook for now while I'm fumbling"
+
+ This reverts commit a21b6bb60ac1c07ebd161534a4ea63bfde50dcdf.
+
+commit de2e71c4923a0282df74dbe37d087c34b4ddd279
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 12:25:20 2010 -0600
+
+ fix man page delivery path
+
+commit a8dbe082960dc9bdd44c6e4b1198423c4e566029
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 12:18:28 2010 -0600
+
+ install altosui man page
+
+commit 5cc933039e4763b8675611c63b6147b42878a2bb
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 12:16:19 2010 -0600
+
+ fix permissions on installed jar file, switch from ao-view to altosui in
+ the desktop file
+
+commit 138009e9fad01f79df4c3820fbc206f78688bdce
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 12:06:01 2010 -0600
+
+ update Debian standards version
+
+commit c280071b7db4e9a7af31dc5740eb8d27f137950e
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 12:04:13 2010 -0600
+
+ fix up the wrapper's path to the jar file
+
+commit 5f2f6a8f9ba56be867888758848bc7f152ccbd47
+Merge: 63bd34c 9d1b27f
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Aug 27 11:00:31 2010 -0700
+
+ Merge remote branch 'origin/master' into new-packet-format
+
+commit 63bd34cd1b5a411489e8c3ab377f0fe0eec11f67
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Aug 27 10:58:55 2010 -0700
+
+ altosui: add elevation and range information
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 72a18502e40f55cbba6418dc94315517881cd411
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 11:51:24 2010 -0600
+
+ add an install target for altosui
+
+commit 72c33a72ee105ec692dad62d6d9c1ad40b89bfe8
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 11:45:19 2010 -0600
+
+ add install target for libaltos
+
+commit a21b6bb60ac1c07ebd161534a4ea63bfde50dcdf
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 11:26:29 2010 -0600
+
+ lose the prebuild hook for now while I'm fumbling
+
+commit 9ea94411c9730f7a271366d309ab4827beeeb839
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 11:17:54 2010 -0600
+
+ add a dummy install target
+
+commit c443f43f8dee6e0fcbcecf9d09e948fd928b7af4
+Merge: 2950431 2923cf5
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri Aug 27 03:08:53 2010 -0600
+
+ Merge branch 'new-packet-format' of ssh://git.gag.com/scm/git/fw/altos into new-package-format
+
+commit 2923cf5057f9cef110dd547d8677ea5b60e00796
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Aug 27 00:10:29 2010 -0700
+
+ altos: prepare for sdcc 2.9.1
+
+ A few minor language changes -- non-standard keywords are now prefixed
+ with __, such as 'at', 'interrupt', 'naked'.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 68967157cee620ebedcc8c2ffd6fc7656532087b
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:55:44 2010 -0700
+
+ altosui: command line args are converted to csv format
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7e0506dc2014b7178f52b950e8c1cb820b35f9c6
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:54:53 2010 -0700
+
+ altosui: Remove debug printf from AltosState.java
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 49364608b59de7421ab00d87d2685bc3b5f58411
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:53:06 2010 -0700
+
+ altosui: When parsing saved telem files, errors shouldn't abort file
+
+ Make syntax errors in telem files just skip the current line and move
+ on to the next one instead of abandoning the whole file.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a16db143fc7ca72dc91e7989420049192114642d
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:50:51 2010 -0700
+
+ altosui: Serial line is in UTF-8 encoding. Deal with it.
+
+ We read bytes from the serial line and need to convert each line into
+ a string. So, save the bytes and at EOL, pass the whole mess to the
+ string constructor with the appropriate encoding info.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0942912163255523d923140c01afbdb5da1c19b5
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:49:37 2010 -0700
+
+ altosui: Add support for old (version < 3) telemetry files
+
+ This lets the code read telemetry files from pre-released versions of
+ the software. Not strictly necessary for production, but useful for
+ analysing old files.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e383595cd281687de903fb6176564bbef270cb83
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:47:38 2010 -0700
+
+ altosui: AltosEepromReader was mis-setting boost tick
+
+ It was supposed to use record.tick instead of the (unset) state.tick
+ value.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 651f6102ac79459fc8d5679d852c963dcb5bb3fc
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:44:25 2010 -0700
+
+ altosui: add rssi and distance/dir from pad to CSV files
+
+ Just adds a couple more fields to the CSV files that might be interesting.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3dc67c1401976d6e9e2e942d5a4707a4810a0404
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:43:00 2010 -0700
+
+ altosui: Add AltosGreatCircle constructors
+
+ This adds constructurs from AltosGPS pairs and also one from empty
+ args (which defines both distance and bearing as 0).
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f0fd423d0bf83bc5c3f9d39e9c09397fbe8caed2
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:41:26 2010 -0700
+
+ altosui: Move number parsing code to Altos general class
+
+ This moves these shared functions to the global shared class.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 68b2b66d7574dfd0bd5e3571b8ffad32ca5d2b73
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 23:37:29 2010 -0700
+
+ altos: mark gps date written only after it gets into eeprom
+
+ Data logging doesn't start until boost detect occurs. As the GPS date
+ is only logged once, if that happens before logging is written to the
+ flash, then the GPS date will never get saved.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aa6c27df5db6bdae59d00affccb891854a6caa18
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 15:59:09 2010 -0700
+
+ altos: print GPS state flags in GPS 'g' command
+
+ Having the GPS state information can help with GPS debugging.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 34055129b4008f6a9833887b12dee39ffa408002
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 26 15:57:09 2010 -0700
+
+ altos: always rebuild ao_product.c to track git version
+
+ The git version is built into ao_product.c and saved in eeprom log
+ files, providing useful diagnostics about the firmware revision used
+ for each flight. However, if ao_product.c isn't recompiled, then the
+ updated version won't be included. Force recompilation of this file
+ each time make is run to ensure that the final output contains an
+ updated version number.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 99400fdc0f19ef538fc362dde5c3ab5b7cdac409
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 24 16:43:38 2010 -0700
+
+ altosui: flush replies from serial link when entering debug mode
+
+ We use replies in debug mode a lot and depend on them matching the
+ expected parameters. The case which caused trouble was using
+ TeleMetrum to reprogram TeleDongle -- sending the 'm 0' command (to
+ disable telemetry monitoring on TeleDongle) to the TeleMetrum caused
+ it to reply 'Syntax Error' which confused the subsequent flashing
+ operation. Flushing that reply gets things back in sync.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ba086cc77273efe5397f60dcaccd1e3771441481
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 24 04:02:27 2010 -0700
+
+ altosui: write USB serial number string while flashing
+
+ USB serial number is encoded in UCS2 as a part of the string
+ descriptors. Place those right after the other rom config bits so that
+ altosui can find it. altosui is changed to write the serial number there.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 220f3afdaa432c65f8ad45be7cdbe5c8a3616db3
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 24 04:01:47 2010 -0700
+
+ altosui: always display romconfig ui while flashing
+
+commit f62b2aa08ebfd912b3c732397d43ff9f6162ec88
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 24 04:01:14 2010 -0700
+
+ altosui: fetch existing romconfig for flashing
+
+commit d93787284c8e514a929edb9f944c98ae0206a33f
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 24 03:59:09 2010 -0700
+
+ altosui: Delay mapping Flash UI until flashing actually starts
+
+ The flash operation may be abandoned before it even starts; this makes
+ sure the UI doesn't flash up on the screen.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7d44cbd621d2b113ac2b802ef17e3d8a660ce7f2
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 24 03:58:00 2010 -0700
+
+ altosui: disable radio monitoring while using serial line for debugging
+
+commit 7bd220dfd9b3fb0e42eb90c3b37eb7b4169eb21b
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 24 00:29:11 2010 -0700
+
+ altosui: Add ability to create CSV file from telem or eeprom files
+
+ This creates a comma separated value file to export data for
+ external programs.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 634a550149e7c344a22a637ba484f115592b1018
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 23:15:05 2010 -0700
+
+ altosui: refactor logfile chooser dialog to share more code
+
+ Move file opening logic into logfile chooser as it can be shared that way.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a55b132668a819cc26478a609cb79bd9190deb9d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 23:01:36 2010 -0700
+
+ altosui: Separate out log file choosing dialog to share with CSV generator
+
+ This dialog will be shared with the CSV file generating code, so split
+ it out instead of duplicating it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 295043112ccde35092945c286596f9045ee6fa05
+Merge: 2007288 ef8376c
+Author: Bdale Garbee <bdale@gag.com>
+Date: Mon Aug 23 23:11:22 2010 -0600
+
+ Merge branch 'new-packet-format' of ssh://git.gag.com/scm/git/fw/altos into new-package-format
+
+commit ef8376c4dd8262a34e02b6bb9e19e907ac2f4330
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 22:08:30 2010 -0700
+
+ altosui: make default Manifest look for built-in freetts
+
+commit 56b906f535ac2f86bcab71addbbcd376d74f6a73
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 22:03:36 2010 -0700
+
+ altos: Place rom config variables in fixed location
+
+ The device serial number and radio calibration values are stored in
+ flash, mostly so that TeleDongle gets them saved.
+
+ Placing them in well-known locations (starting at 0xa0) makes it
+ possible to find the previous configuration and to re-write it
+ easily, without requiring the .map file.
+
+ altosui doesn't have the .map file parsing code, so it relies upon
+ this new technique. As a benefit, it reads the old values from the
+ device before reprogramming it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4c0c099716197ef7539be0cf55bbb164f6804958
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 22:02:21 2010 -0700
+
+ altosui: Finish device programming code
+
+ Altosui can now reprogram Altusmetrum devices.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bd2b44ddd61fadd8bf8ee6bf783ce019b1be7cc0
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 22:01:38 2010 -0700
+
+ altosui: Remove debug printf from AltosRomconfig
+
+commit c3f57ffdb6c74de90d982eacd604e658ce9b00a5
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 22:01:11 2010 -0700
+
+ altosui: flush serial output before waiting for reply
+
+commit 8857ac5e43eac6db8d5594b8864df497a712242b
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 22:00:16 2010 -0700
+
+ altosui: remove debug printf from AltosHexfile
+
+commit b1758be01397fd49c441f40852f3558fe9343a2d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 21:58:50 2010 -0700
+
+ altosui: Add lots more cc1111 debug interface functions
+
+ These are sufficient to program the flash.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f9e80f39bc39e5882bfe75f959b6501cb3277cd2
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 21:55:49 2010 -0700
+
+ libaltos: use pipe to wake up getchar on close. use mutexes
+
+commit 86f7b9314b042f2e512fdf35067817e68532867b
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 21:54:47 2010 -0700
+
+ altosui: pad TM config dialog values to avoid clipping descenders
+
+commit b8519b8669ff54741dd738ac343fbd2424451247
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 21:53:37 2010 -0700
+
+ ao-dumplog: Fix --remote and --channel options to actually work
+
+commit ebeb13688a9a5442c838641ede6ba0dc92c9a1a4
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 14:32:58 2010 -0700
+
+ altosui: Add debug dongle API, split flash UI out
+
+ Create an API to talk through the debug port on another AltOS
+ device. Split the flash UI out from the flash implementation so that a
+ command line flash utility can be written.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7f8d7978606abe544b1b9b6065c5480ed813b8ec
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Aug 23 11:53:19 2010 -0700
+
+ altosui: Add .ihx file reading code and stub out flashing UI
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2007288da8a83e3aa925e11cc196f1c65aab2e5c
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Aug 5 15:00:15 2010 -0400
+
+ working on java packaging details
+
+commit 44b26dd550eef789e70082ccaa46d7d430c67bce
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Aug 5 15:15:04 2010 -0400
+
+ add freetts as a build dep
+
+commit 0e17853c08f77debef3e8cf82e9cdb6a5079fc9b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 22 23:06:15 2010 -0700
+
+ altosui: Set callsign when fetching eeprom data over the air
+
+ The updated firmware places the callsign in each packet to comply with
+ regulations, this ensures that TeleDongle has the current callsign
+ configured.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 953bc3438b10b21f3d65d292356c4ab2de23cddd
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Aug 22 23:05:20 2010 -0700
+
+ altosui: Add TeleMetrum configuration
+
+ This presents a dialog with all of the user-settable options in the
+ TeleMetrum set for editing. Combo boxes are used for everything except
+ the callsign.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e1463d8e265dfd42c824d90088cd2a51b4cf8131
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Aug 21 17:57:31 2010 -0700
+
+ altosui: Make teledongle callsign configurable
+
+ Teledongle uses the callsign in packet mode; this provides a way to
+ set that.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 09252ec22d58e946494e4ca2cf367bf3bbe1cc50
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Aug 21 17:09:41 2010 -0700
+
+ altos: Define USB product ID in per-product Makefile.defs file
+
+ This allows Win7 to tell which kind of device is connected purely by
+ USB id as it doesn't expose the USB product ID string to user space.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 22800dc094797e1e0ad99124198809d0360f7556
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 17 18:22:28 2010 -0700
+
+ altosui: Select devices by USB vendor/product ID.
+
+ Because Win7 doesn't expose the product name, we're swtiching to using
+ the USB idProduct/idVendor values. This patch adds support for
+ selecting devices by those new IDs.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d14c96663a1027164fa30ed89b53f5a9d3fdb82b
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Aug 17 18:19:43 2010 -0700
+
+ libaltos: integrate Windows support.
+
+ This adds Windows support for discovery and I/O.
+
+ The API to the library is mostly unchanged, except that it now exports
+ product and vendor USB IDs as Win7 doesn't expose the product name
+ anywhere that we've been able to find, so we'll be updating the
+ firmware to use unique idProduct values for each product.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9d1b27fa147fc8b765d5be165ebef7ee0f85bd37
+Author: Bdale Garbee <bdale@gag.com>
+Date: Wed Aug 11 22:11:50 2010 -0400
+
+ update changelogs for Debian build
+
commit b6da90b4627dde1fe88240c38c51559d8f781dd0
Author: Bdale Garbee <bdale@gag.com>
Date: Wed Aug 11 17:15:39 2010 -0400
update changelogs for Debian build
+commit 294d9c7db21eaf1e71504dbcca5040371abcce55
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Aug 7 22:30:55 2010 -0400
+
+ ao-dumplog: add --channel option (for use with -R option)
+
+ Sets the channel when downloading data with the -R option.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f317f1324b69b4241f4bb192e164b33d712d5a43
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Aug 7 00:42:25 2010 -0400
+
+ altosui: Start adding code to write csv files from eeprom/telem files
+
+ This is a start to code which can write out a csv file full of flight
+ data from either an eeprom or telem input file. It's not hooked up,
+ but the restructuring necessary is finished and the output is started.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4738cb2fc639adb1d9237e6c903479f0690dd81a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Aug 7 00:40:59 2010 -0400
+
+ altos: add callsign to packet mode, increase payload to 64 bytes
+
+ Untested, but it 'should' work. Need to add callsign setting to packet
+ mode users.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b7699a5907e64bc7547fcc27e73f4a35bbaabfff
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Aug 6 13:09:21 2010 -0400
+
+ altosui: Add comments to Eeprom reader
+
+commit 0e917f3ff822616adb147517ac961422e5fedbfd
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 5 22:49:53 2010 -0400
+
+ altosui: Compute flight state from eeprom data
+
+ This lets eeprom files be used to replay flights.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
commit a0a9b445a4d379730b67720f8d7b682d5206a582
Author: Bdale Garbee <bdale@gag.com>
Date: Thu Aug 5 15:16:48 2010 -0400
working on java packaging details
+commit d8bf05f7ad55964c9bce0551e58f4ef6c9f721ad
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 5 13:50:18 2010 -0400
+
+ altosui: Split flight record out of telemetry class
+
+ This will permit either telemetry or eeprom data to be used to
+ construct the sequence of flight events for reply or data generation.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 85a670b5a904d6750d0f179ae307baeb8fc7cbd2
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Aug 5 13:40:17 2010 -0400
+
+ altosui: Explicitly initialize Altos class
+
+ Because the Altos class is never instantiated, the static initializers
+ are never called, leaving the string to state mapping empty. Hand-code
+ the call to the initialer instead.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
commit 02f17f2cd26189e2676a9dc0d86bd959ed0bc3f4
Author: Bdale Garbee <bdale@gag.com>
Date: Thu Aug 5 00:54:05 2010 -0400
move to science menu
+commit 9e8f7f75442303f9bfa99a0435984f5d36863ae6
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 31 10:34:21 2010 -0700
+
+ altosui: Split status and info panels into separate files
+
+ This moves some code out of AltosUI.java into separate files
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9c9b35254c693b3ade42b24d1e29eaf31e6ba2aa
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 31 10:24:56 2010 -0700
+
+ altosui: Clear displayed data rows as needed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 88e0137a60d7a13ddb7781befa76650e13ad44ae
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 31 10:07:38 2010 -0700
+
+ altosui: Merge gps date and time classes into gps class
+
+ No reason to split out the date and time information from the other gps info.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1c3b2fe357d6acf28f48aeddd91693f10381be51
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 31 10:05:15 2010 -0700
+
+ altosui: Capture config and version info in .eeprom files
+
+ Instead of only writing the serial number to the .eeprom file, write
+ all of the config values and all of the version reply to the .eeprom
+ file. The config values, in particular, contain the accelerometer
+ calibration data which is needed to correctly compute acceleration
+ from the captured accelerometer data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e286eb61ad2a90746c1c31f95d26d5edb48738d3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 31 09:57:49 2010 -0700
+
+ altosui: rename AltosEeprom -> AltosEepromDownload, split out Altos constants
+
+ Renames the eeprom downloading code and adds a new file to share the
+ flight data constants across the various UI modules.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
commit e3a9e3815db3f290e28b40ae02aa654f515cfc37
Author: Bdale Garbee <bdale@gag.com>
Date: Sat Jul 31 10:55:27 2010 -0600
(touch ChangeLog; echo 'git directory not found: installing possibly empty changelog.' >&2)
dist-hook: ChangeLog
+
+fat:
+ cd ao-tools/altosui && $(MAKE) fat
-*.class
+windows/
+linux/
+macosx/
+fat/
+Manifest.txt
+Manifest-fat.txt
+libaltosJNI
+classes
altosui
+altosui-test
+classaltosui.stamp
+Altos-Linux-*.tar.bz2
+Altos-Mac-*.zip
+Altos-Windows-*.exe
+*.dll
+*.dylib
+*.so
+*.jar
+*.class
static final int AO_GPS_DATE_VALID = (1 << 6);
static final int AO_GPS_NUM_SAT_SHIFT = 0;
static final int AO_GPS_NUM_SAT_MASK = 0xf;
+
+ static boolean isspace(int c) {
+ switch (c) {
+ case ' ':
+ case '\t':
+ return true;
+ }
+ return false;
+ }
+
+ static boolean ishex(int c) {
+ if ('0' <= c && c <= '9')
+ return true;
+ if ('a' <= c && c <= 'f')
+ return true;
+ if ('A' <= c && c <= 'F')
+ return true;
+ return false;
+ }
+
+ static boolean ishex(String s) {
+ for (int i = 0; i < s.length(); i++)
+ if (!ishex(s.charAt(i)))
+ return false;
+ return true;
+ }
+
+ static int fromhex(int c) {
+ if ('0' <= c && c <= '9')
+ return c - '0';
+ if ('a' <= c && c <= 'f')
+ return c - 'a' + 10;
+ if ('A' <= c && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+ }
+
+ static int fromhex(String s) throws NumberFormatException {
+ int c, v = 0;
+ for (int i = 0; i < s.length(); i++) {
+ c = s.charAt(i);
+ if (!ishex(c)) {
+ if (i == 0)
+ throw new NumberFormatException(String.format("invalid hex \"%s\"", s));
+ return v;
+ }
+ v = v * 16 + fromhex(c);
+ }
+ return v;
+ }
+
+ static boolean isdec(int c) {
+ if ('0' <= c && c <= '9')
+ return true;
+ return false;
+ }
+
+ static boolean isdec(String s) {
+ for (int i = 0; i < s.length(); i++)
+ if (!isdec(s.charAt(i)))
+ return false;
+ return true;
+ }
+
+ static int fromdec(int c) {
+ if ('0' <= c && c <= '9')
+ return c - '0';
+ return -1;
+ }
+
+ static int fromdec(String s) throws NumberFormatException {
+ int c, v = 0;
+ int sign = 1;
+ for (int i = 0; i < s.length(); i++) {
+ c = s.charAt(i);
+ if (i == 0 && c == '-') {
+ sign = -1;
+ } else if (!isdec(c)) {
+ if (i == 0)
+ throw new NumberFormatException(String.format("invalid number \"%s\"", s));
+ return v;
+ } else
+ v = v * 10 + fromdec(c);
+ }
+ return v * sign;
+ }
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+public class AltosCRCException extends Exception {
+ public int rssi;
+
+ public AltosCRCException (int in_rssi) {
+ rssi = in_rssi;
+ }
+}
import java.lang.*;
import java.io.*;
+import java.text.*;
+import java.util.*;
+
import altosui.AltosRecord;
+import altosui.AltosReader;
public class AltosCSV {
- File name;
- PrintStream out;
- boolean header_written;
+ File name;
+ PrintStream out;
+ boolean header_written;
+ boolean seen_boost;
+ int boost_tick;
+ LinkedList<AltosRecord> pad_records;
+ AltosState state;
static final int ALTOS_CSV_VERSION = 1;
* flight number
* callsign
* time (seconds since boost)
+ * rssi
*
* Flight status
* state
* acceleration (m/s²)
* pressure (mBar)
* altitude (m)
+ * height (m)
* accelerometer speed (m/s)
* barometer speed (m/s)
* temp (°C)
* hour (0-23)
* minute (0-59)
* second (0-59)
+ * from_pad_dist (m)
+ * from_pad_azimuth (deg true)
+ * from_pad_range (m)
+ * from_pad_elevation (deg from horizon)
*
* GPS Sat data
* hdop
*/
void write_general_header() {
- out.printf("version serial flight call time");
+ out.printf("version serial flight call time rssi");
}
void write_general(AltosRecord record) {
- out.printf("%s,%d,%d,%s,%d",
- record.version, record.serial, record.flight, record.callsign, record.tick);
+ out.printf("%s,%d,%d,%s,%8.2f,%4d",
+ record.version, record.serial, record.flight, record.callsign,
+ (double) record.time,
+ record.rssi);
}
void write_flight_header() {
}
void write_flight(AltosRecord record) {
- out.printf("%d,%s", record.state, record.state());
+ out.printf("%d,%8s", record.state, record.state());
+ }
+
+ void write_basic_header() {
+ out.printf("acceleration pressure altitude height accel_speed baro_speed temperature battery_voltage drogue_voltage main_voltage");
+ }
+
+ void write_basic(AltosRecord record) {
+ out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f",
+ record.acceleration(),
+ record.pressure(),
+ record.altitude(),
+ record.height(),
+ record.accel_speed(),
+ state.baro_speed,
+ record.temperature(),
+ record.battery_voltage(),
+ record.drogue_voltage(),
+ record.main_voltage());
+ }
+
+ 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");
+ }
+
+ void write_gps(AltosRecord record) {
+ AltosGPS gps = record.gps;
+ if (gps == null)
+ gps = new AltosGPS();
+
+ AltosGreatCircle from_pad = state.from_pad;
+ if (from_pad == null)
+ from_pad = new AltosGreatCircle();
+
+ out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%6d,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f",
+ gps.connected?1:0,
+ gps.locked?1:0,
+ gps.nsat,
+ gps.lat,
+ gps.lon,
+ gps.alt,
+ gps.year,
+ gps.month,
+ gps.day,
+ gps.hour,
+ gps.minute,
+ gps.second,
+ from_pad.distance,
+ state.range,
+ from_pad.bearing,
+ state.elevation);
}
void write_header() {
out.printf("# "); write_general_header();
out.printf(" "); write_flight_header();
+ out.printf(" "); write_basic_header();
+ out.printf(" "); write_gps_header();
+ out.printf ("\n");
+ }
+
+ void write_one(AltosRecord record) {
+ state = new AltosState(record, state);
+ write_general(record); out.printf(",");
+ write_flight(record); out.printf(",");
+ write_basic(record); out.printf(",");
+ write_gps(record);
out.printf ("\n");
}
+ void flush_pad() {
+ while (!pad_records.isEmpty()) {
+ write_one (pad_records.remove());
+ }
+ }
+
public void write(AltosRecord record) {
if (!header_written) {
write_header();
header_written = true;
}
- write_general(record); out.printf(",");
- write_flight(record);
- out.printf ("\n");
+ if (!seen_boost) {
+ if (record.state >= Altos.ao_flight_boost) {
+ seen_boost = true;
+ boost_tick = record.tick;
+ flush_pad();
+ }
+ }
+ if (seen_boost)
+ write_one(record);
+ else
+ pad_records.add(record);
}
public PrintStream out() {
return out;
}
+ public void close() {
+ if (!pad_records.isEmpty()) {
+ boost_tick = pad_records.element().tick;
+ flush_pad();
+ }
+ out.close();
+ }
+
+ public void write(AltosReader reader) {
+ AltosRecord record;
+
+ reader.write_comments(out());
+ try {
+ for (;;) {
+ record = reader.read();
+ if (record == null)
+ break;
+ write(record);
+ }
+ } catch (IOException ie) {
+ System.out.printf("IOException\n");
+ } catch (ParseException pe) {
+ System.out.printf("ParseException %s\n", pe.getMessage());
+ }
+ }
+
public AltosCSV(File in_name) throws FileNotFoundException {
name = in_name;
out = new PrintStream(name);
+ pad_records = new LinkedList<AltosRecord>();
+ }
+
+ public AltosCSV(String in_string) throws FileNotFoundException {
+ this(new File(in_string));
}
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import altosui.AltosLogfileChooser;
+import altosui.AltosCSV;
+
+public class AltosCSVUI
+ extends JDialog
+ implements Runnable, ActionListener
+{
+ JFrame frame;
+ Thread thread;
+ AltosReader reader;
+ AltosCSV writer;
+
+ public void run() {
+ AltosLogfileChooser chooser;
+
+ chooser = new AltosLogfileChooser(frame);
+ reader = chooser.runDialog();
+ if (reader == null)
+ return;
+ JFileChooser csv_chooser;
+
+ File file = chooser.file();
+ String path = file.getPath();
+ int dot = path.lastIndexOf(".");
+ if (dot >= 0)
+ path = path.substring(0,dot);
+ path = path.concat(".csv");
+ csv_chooser = new JFileChooser(path);
+ int ret = csv_chooser.showSaveDialog(frame);
+ if (ret == JFileChooser.APPROVE_OPTION) {
+ try {
+ writer = new AltosCSV(csv_chooser.getSelectedFile());
+ } catch (FileNotFoundException ee) {
+ JOptionPane.showMessageDialog(frame,
+ file.getName(),
+ "Cannot open file",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ writer.write(reader);
+ reader.close();
+ writer.close();
+ }
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ }
+
+ public AltosCSVUI(JFrame in_frame) {
+ frame = in_frame;
+ thread = new Thread(this);
+ thread.start();
+ }
+}
void start_serial() throws InterruptedException {
if (remote) {
- serial_line.printf("m 0\n");
serial_line.set_channel(AltosPreferences.channel());
serial_line.set_callsign(AltosPreferences.callsign());
serial_line.printf("p\n");
+ serial_line.flush_input();
}
}
void stop_serial() throws InterruptedException {
if (remote) {
- serial_line.printf("~\n");
- serial_line.flush();
+ serial_line.printf("~");
+ serial_line.flush_output();
}
}
import libaltosJNI.*;
-public class AltosConfigUI extends JDialog implements ActionListener, ItemListener, DocumentListener {
+public class AltosConfigUI
+ extends JDialog
+ implements ActionListener, ItemListener, DocumentListener
+{
Container pane;
Box box;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
+ c.ipady = 5;
version_label = new JLabel("Software version:");
pane.add(version_label, c);
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
+ c.ipady = 5;
version_value = new JLabel("");
pane.add(version_value, c);
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
+ c.ipady = 5;
serial_label = new JLabel("Serial:");
pane.add(serial_label, c);
c.weightx = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
+ c.ipady = 5;
serial_value = new JLabel("");
pane.add(serial_value, c);
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
- c.ipady = 3;
+ c.ipady = 5;
main_deploy_label = new JLabel("Main Deploy Altitude(m):");
pane.add(main_deploy_label, c);
/* Buttons */
c = new GridBagConstraints();
c.gridx = 0; c.gridy = 7;
- c.gridwidth = 2;
+ c.gridwidth = 6;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
save.setActionCommand("save");
c = new GridBagConstraints();
- c.gridx = 2; c.gridy = 7;
- c.gridwidth = 2;
+ c.gridx = 0; c.gridy = 7;
+ c.gridwidth = 6;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
c.insets = il;
reset.setActionCommand("reset");
c = new GridBagConstraints();
- c.gridx = 4; c.gridy = 7;
- c.gridwidth = 2;
+ c.gridx = 0; c.gridy = 7;
+ c.gridwidth = 6;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LINE_END;
c.insets = il;
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.lang.*;
+import java.io.*;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.LinkedList;
+import java.util.Iterator;
+import altosui.AltosSerial;
+import altosui.AltosRomconfig;
+
+public class AltosDebug extends AltosSerial {
+
+ public static final byte WR_CONFIG = 0x1d;
+ public static final byte RD_CONFIG = 0x24;
+ public static final byte CONFIG_TIMERS_OFF = (1 << 3);
+ public static final byte CONFIG_DMA_PAUSE = (1 << 2);
+ public static final byte CONFIG_TIMER_SUSPEND = (1 << 1);
+ public static final byte SET_FLASH_INFO_PAGE = (1 << 0);
+
+ public static final byte GET_PC = 0x28;
+ public static final byte READ_STATUS = 0x34;
+ public static final byte STATUS_CHIP_ERASE_DONE = (byte) (1 << 7);
+ public static final byte STATUS_PCON_IDLE = (1 << 6);
+ public static final byte STATUS_CPU_HALTED = (1 << 5);
+ public static final byte STATUS_POWER_MODE_0 = (1 << 4);
+ public static final byte STATUS_HALT_STATUS = (1 << 3);
+ public static final byte STATUS_DEBUG_LOCKED = (1 << 2);
+ public static final byte STATUS_OSCILLATOR_STABLE = (1 << 1);
+ public static final byte STATUS_STACK_OVERFLOW = (1 << 0);
+
+ public static final byte SET_HW_BRKPNT = 0x3b;
+ public static byte HW_BRKPNT_N(byte n) { return (byte) ((n) << 3); }
+ public static final byte HW_BRKPNT_N_MASK = (0x3 << 3);
+ public static final byte HW_BRKPNT_ENABLE = (1 << 2);
+
+ public static final byte HALT = 0x44;
+ public static final byte RESUME = 0x4c;
+ public static byte DEBUG_INSTR(byte n) { return (byte) (0x54|(n)); }
+ public static final byte STEP_INSTR = 0x5c;
+ public static byte STEP_REPLACE(byte n) { return (byte) (0x64|(n)); }
+ public static final byte GET_CHIP_ID = 0x68;
+
+
+ boolean debug_mode;
+
+ void ensure_debug_mode() {
+ if (!debug_mode) {
+ printf("D\n");
+ flush_input();
+ debug_mode = true;
+ }
+ }
+
+ void dump_memory(String header, int address, byte[] bytes, int start, int len) {
+ System.out.printf("%s\n", header);
+ for (int j = 0; j < len; j++) {
+ if ((j & 15) == 0) {
+ if (j != 0)
+ System.out.printf("\n");
+ System.out.printf ("%04x:", address + j);
+ }
+ System.out.printf(" %02x", bytes[start + j]);
+ }
+ System.out.printf("\n");
+ }
+
+ /*
+ * Write target memory
+ */
+ public void write_memory(int address, byte[] bytes, int start, int len) {
+ ensure_debug_mode();
+// dump_memory("write_memory", address, bytes, start, len);
+ printf("O %x %x\n", len, address);
+ for (int i = 0; i < len; i++)
+ printf("%02x", bytes[start + i]);
+ }
+
+ public void write_memory(int address, byte[] bytes) {
+ write_memory(address, bytes, 0, bytes.length);
+ }
+
+ /*
+ * Read target memory
+ */
+ public byte[] read_memory(int address, int length)
+ throws IOException, InterruptedException {
+ byte[] data = new byte[length];
+
+ flush_input();
+ ensure_debug_mode();
+ printf("I %x %x\n", length, address);
+ int i = 0;
+ int start = 0;
+ while (i < length) {
+ String line = get_reply().trim();
+ if (!Altos.ishex(line) || line.length() % 2 != 0)
+ throw new IOException(
+ String.format
+ ("Invalid reply \"%s\"", line));
+ int this_time = line.length() / 2;
+ for (int j = 0; j < this_time; j++)
+ data[start + j] = (byte) ((Altos.fromhex(line.charAt(j*2)) << 4) +
+ Altos.fromhex(line.charAt(j*2+1)));
+ start += this_time;
+ i += this_time;
+ }
+// dump_memory("read_memory", address, data, 0, length);
+
+ return data;
+ }
+
+ /*
+ * Write raw bytes to the debug link using the 'P' command
+ */
+ public void write_bytes(byte[] bytes) throws IOException {
+ int i = 0;
+ ensure_debug_mode();
+ while (i < bytes.length) {
+ int this_time = bytes.length - i;
+ if (this_time > 8)
+ this_time = 0;
+ printf("P");
+ for (int j = 0; j < this_time; j++)
+ printf(" %02x", bytes[i+j]);
+ printf("\n");
+ i += this_time;
+ }
+ }
+
+ public void write_byte(byte b) throws IOException {
+ byte[] bytes = { b };
+ write_bytes(bytes);
+ }
+
+ /*
+ * Read raw bytes from the debug link using the 'G' command
+ */
+ public byte[] read_bytes(int length)
+ throws IOException, InterruptedException {
+
+ flush_input();
+ ensure_debug_mode();
+ printf("G %x\n", length);
+ int i = 0;
+ byte[] data = new byte[length];
+ while (i < length) {
+ String line = get_reply().trim();
+ String tokens[] = line.split("\\s+");
+ for (int j = 0; j < tokens.length; j++) {
+ if (!Altos.ishex(tokens[j]) ||
+ tokens[j].length() != 2)
+ throw new IOException(
+ String.format
+ ("Invalid read_bytes reply \"%s\"", line));
+ try {
+ data[i + j] = (byte) Integer.parseInt(tokens[j], 16);
+ } catch (NumberFormatException ne) {
+ throw new IOException(
+ String.format
+ ("Invalid read_bytes reply \"%s\"", line));
+ }
+ }
+ i += tokens.length;
+ }
+ return data;
+ }
+
+ public byte read_byte() throws IOException, InterruptedException {
+ return read_bytes(1)[0];
+ }
+
+ public byte debug_instr(byte[] instruction) throws IOException, InterruptedException {
+ byte[] command = new byte[1 + instruction.length];
+ command[0] = DEBUG_INSTR((byte) instruction.length);
+ for (int i = 0; i < instruction.length; i++)
+ command[i+1] = instruction[i];
+ write_bytes(command);
+ return read_byte();
+ }
+
+ public byte resume() throws IOException, InterruptedException {
+ write_byte(RESUME);
+ return read_byte();
+ }
+
+ public int read_uint16() throws IOException, InterruptedException {
+ byte[] d = read_bytes(2);
+ return ((int) (d[0] & 0xff) << 8) | (d[1] & 0xff);
+ }
+
+ public int read_uint8() throws IOException, InterruptedException {
+ byte[] d = read_bytes(1);
+ return (int) (d[0] & 0xff);
+ }
+
+ public int get_chip_id() throws IOException, InterruptedException {
+ write_byte(GET_CHIP_ID);
+ return read_uint16();
+ }
+
+ public int get_pc() throws IOException, InterruptedException {
+ write_byte(GET_PC);
+ return read_uint16();
+ }
+
+ public byte read_status() throws IOException, InterruptedException {
+ write_byte(READ_STATUS);
+ return read_byte();
+ }
+
+ static final byte LJMP = 0x02;
+
+ public void set_pc(int pc) throws IOException, InterruptedException {
+ byte high = (byte) (pc >> 8);
+ byte low = (byte) pc;
+ byte[] jump_mem = { LJMP, high, low };
+ debug_instr(jump_mem);
+ }
+
+ public boolean check_connection() throws IOException, InterruptedException {
+ byte reply = read_status();
+ if ((reply & STATUS_CHIP_ERASE_DONE) == 0)
+ return false;
+ if ((reply & STATUS_PCON_IDLE) != 0)
+ return false;
+ if ((reply & STATUS_POWER_MODE_0) == 0)
+ return false;
+ return true;
+ }
+
+ public AltosRomconfig romconfig() {
+ try {
+ byte[] bytes = read_memory(0xa0, 10);
+ return new AltosRomconfig(bytes, 0);
+ } catch (IOException ie) {
+ } catch (InterruptedException ie) {
+ }
+ return new AltosRomconfig();
+ }
+
+ /*
+ * Reset target
+ */
+ public void reset() {
+ printf ("R\n");
+ }
+}
\ No newline at end of file
System.err.println("Native library failed to load.\n" + e);
}
}
+ public final static int AltusMetrum = libaltosConstants.USB_PRODUCT_ALTUSMETRUM;
public final static int TeleMetrum = libaltosConstants.USB_PRODUCT_TELEMETRUM;
public final static int TeleDongle = libaltosConstants.USB_PRODUCT_TELEDONGLE;
public final static int TeleTerra = libaltosConstants.USB_PRODUCT_TELETERRA;
public boolean matchProduct(int want_product) {
+ if (!isAltusMetrum())
+ return false;
+
if (want_product == Any)
return true;
if (want_product == BaseStation)
return matchProduct(TeleDongle) || matchProduct(TeleTerra);
- if (!isAltusMetrum())
- return false;
-
int have_product = getProduct();
- if (want_product == have_product)
+ if (have_product == AltusMetrum) /* old devices match any request */
return true;
- if (have_product != libaltosConstants.USB_PRODUCT_ALTUSMETRUM)
- return false;
-
- String name = getName();
+ if (want_product == have_product)
+ return true;
- if (name == null)
- return false;
- if (want_product == libaltosConstants.USB_PRODUCT_TELEMETRUM)
- return name.startsWith("TeleMetrum");
- if (want_product == libaltosConstants.USB_PRODUCT_TELEDONGLE)
- return name.startsWith("TeleDongle");
- if (want_product == libaltosConstants.USB_PRODUCT_TELETERRA)
- return name.startsWith("TeleTerra");
return false;
}
if (values == null) {
System.out.printf("invalid line: %s\n", line);
+ continue;
} else if (values[0] != addr) {
System.out.printf("data address out of sync at 0x%x\n",
block * 256 + values[0]);
public void run () {
if (remote) {
- serial_line.printf("m 0\n");
serial_line.set_channel(AltosPreferences.channel());
serial_line.set_callsign(AltosPreferences.callsign());
- serial_line.printf("p\n");
+ serial_line.printf("p\nE 0\n");
+ serial_line.flush_input();
}
monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed);
if (remote)
serial_line.printf("~");
monitor.done();
+ serial_line.flush_output();
serial_line.close();
}
*/
class AltosOrderedRecord extends AltosEepromRecord implements Comparable<AltosOrderedRecord> {
- int index;
+ public int index;
public AltosOrderedRecord(String line, int in_index, int prev_tick)
throws ParseException {
index = in_index;
}
+ public AltosOrderedRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) {
+ super(in_cmd, in_tick, in_a, in_b);
+ index = in_index;
+ }
+
public int compareTo(AltosOrderedRecord o) {
int tick_diff = tick - o.tick;
if (tick_diff != 0)
int gps_tick;
- boolean saw_boost;
-
int boost_tick;
+ boolean saw_gps_date;
+
+ boolean missing_gps_time;
+
public AltosRecord read() throws IOException, ParseException {
for (;;) {
if (record == null) {
if (last_reported)
return null;
last_reported = true;
- return state;
+ return new AltosRecord(state);
}
record = record_iterator.next();
state.tick = record.tick;
switch (record.cmd) {
case Altos.AO_LOG_FLIGHT:
- state.ground_accel = record.a;
- state.flight = record.b;
- seen |= seen_flight;
+ /* recorded when first read from the file */
break;
case Altos.AO_LOG_SENSOR:
state.accel = record.a;
ground_pres += state.pres;
state.ground_pres = (int) (ground_pres / n_pad_samples);
state.flight_pres = state.ground_pres;
- System.out.printf("ground pressure %d altitude %f\n",
- record.b, state.altitude());
ground_accel += state.accel;
state.ground_accel = (int) (ground_accel / n_pad_samples);
state.flight_accel = state.ground_accel;
seen |= seen_deploy;
break;
case Altos.AO_LOG_STATE:
- System.out.printf("state %d\n", record.a);
state.state = record.a;
break;
case Altos.AO_LOG_GPS_TIME:
gps_tick = state.tick;
+ AltosGPS old = state.gps;
state.gps = new AltosGPS();
+
+ /* GPS date doesn't get repeated through the file */
+ if (old != null) {
+ state.gps.year = old.year;
+ state.gps.month = old.month;
+ state.gps.day = old.day;
+ }
state.gps.hour = (record.a & 0xff);
state.gps.minute = (record.a >> 8);
state.gps.second = (record.b & 0xff);
}
break;
case Altos.AO_LOG_GPS_DATE:
- state.gps.year = record.a & 0xff;
+ state.gps.year = (record.a & 0xff) + 2000;
state.gps.month = record.a >> 8;
state.gps.day = record.b & 0xff;
break;
case Altos.AO_LOG_PRODUCT:
break;
case Altos.AO_LOG_SERIAL_NUMBER:
+ state.serial = record.a;
break;
case Altos.AO_LOG_SOFTWARE_VERSION:
break;
public void write_comments(PrintStream out) {
Iterator<AltosOrderedRecord> iterator = records.iterator();
+ out.printf("# Comments\n");
while (iterator.hasNext()) {
AltosOrderedRecord record = iterator.next();
switch (record.cmd) {
out.printf ("# Accel cal: %d %d\n", record.a, record.b);
break;
case Altos.AO_LOG_RADIO_CAL:
- out.printf ("# Radio cal: %d %d\n", record.a);
+ out.printf ("# Radio cal: %d\n", record.a);
break;
case Altos.AO_LOG_MANUFACTURER:
out.printf ("# Manufacturer: %s\n", record.data);
}
}
+ /*
+ * Given an AO_LOG_GPS_TIME record with correct time, and one
+ * missing time, rewrite the missing time values with the good
+ * ones, assuming that the difference between them is 'diff' seconds
+ */
+ void update_time(AltosOrderedRecord good, AltosOrderedRecord bad) {
+
+ int diff = (bad.tick - good.tick + 50) / 100;
+
+ int hour = (good.a & 0xff);
+ int minute = (good.a >> 8);
+ int second = (good.b & 0xff);
+ int flags = (good.b >> 8);
+ int seconds = hour * 3600 + minute * 60 + second;
+
+ int new_seconds = seconds + diff;
+ if (new_seconds < 0)
+ new_seconds += 24 * 3600;
+ int new_second = (new_seconds % 60);
+ int new_minutes = (new_seconds / 60);
+ int new_minute = (new_minutes % 60);
+ int new_hours = (new_minutes / 60);
+ int new_hour = (new_hours % 24);
+
+ bad.a = new_hour + (new_minute << 8);
+ bad.b = new_second + (flags << 8);
+ }
+
/*
* Read the whole file, dumping records into a RB tree so
* we can enumerate them in time order -- the eeprom data
seen = 0;
records = new TreeSet<AltosOrderedRecord>();
+ AltosOrderedRecord last_gps_time = null;
+
int index = 0;
int tick = 0;
+ boolean missing_time = false;
+
try {
for (;;) {
String line = AltosRecord.gets(input);
AltosOrderedRecord record = new AltosOrderedRecord(line, index++, tick);
if (record == null)
break;
+ if (record.cmd == Altos.AO_LOG_INVALID)
+ continue;
tick = record.tick;
- if (!saw_boost && record.cmd == Altos.AO_LOG_STATE &&
- record.a == Altos.ao_flight_boost)
- {
- saw_boost = true;
- boost_tick = state.tick;
+ if (record.cmd == Altos.AO_LOG_FLIGHT) {
+ state.ground_accel = record.a;
+ state.flight = record.b;
+ boost_tick = tick;
+ seen |= seen_flight;
+ }
+
+ /* Two firmware bugs caused the loss of some GPS data.
+ * The flight date would never be recorded, and often
+ * the flight time would get overwritten by another
+ * record. Detect the loss of the GPS date and fix up the
+ * missing time records
+ */
+ if (record.cmd == Altos.AO_LOG_GPS_DATE)
+ saw_gps_date = true;
+
+ /* go back and fix up any missing time values */
+ if (record.cmd == Altos.AO_LOG_GPS_TIME) {
+ last_gps_time = record;
+ if (missing_time) {
+ Iterator<AltosOrderedRecord> iterator = records.iterator();
+ while (iterator.hasNext()) {
+ AltosOrderedRecord old = iterator.next();
+ if (old.cmd == Altos.AO_LOG_GPS_TIME &&
+ old.a == -1 && old.b == -1)
+ {
+ update_time(record, old);
+ }
+ }
+ missing_time = false;
+ }
+ }
+
+ if (record.cmd == Altos.AO_LOG_GPS_LAT) {
+ if (last_gps_time == null || last_gps_time.tick != record.tick) {
+ AltosOrderedRecord add_gps_time = new AltosOrderedRecord(Altos.AO_LOG_GPS_TIME,
+ record.tick,
+ -1, -1, index-1);
+ if (last_gps_time != null)
+ update_time(last_gps_time, add_gps_time);
+ else
+ missing_time = true;
+
+ records.add(add_gps_time);
+ record.index = index++;
+ }
}
records.add(record);
}
public int tick;
public int a;
public int b;
- String data;
+ public String data;
public boolean tick_valid;
- public AltosEepromRecord (String line) throws ParseException {
+ public AltosEepromRecord (String line) {
tick_valid = false;
tick = 0;
a = 0;
data = null;
if (line == null) {
cmd = Altos.AO_LOG_INVALID;
+ data = "";
} else {
- String[] tokens = line.split("\\s+");
+ try {
+ String[] tokens = line.split("\\s+");
- if (tokens[0].length() == 1) {
- if (tokens.length != 4)
- throw new ParseException(line, 0);
- cmd = tokens[0].codePointAt(0);
- tick = Integer.parseInt(tokens[1],16);
- tick_valid = true;
- a = Integer.parseInt(tokens[2],16);
- b = Integer.parseInt(tokens[3],16);
- } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) {
- cmd = Altos.AO_LOG_CONFIG_VERSION;
- data = tokens[2];
- } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) {
- cmd = Altos.AO_LOG_MAIN_DEPLOY;
- a = Integer.parseInt(tokens[2]);
- } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) {
- cmd = Altos.AO_LOG_APOGEE_DELAY;
- a = Integer.parseInt(tokens[2]);
- } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) {
- cmd = Altos.AO_LOG_RADIO_CHANNEL;
- a = Integer.parseInt(tokens[2]);
- } else if (tokens[0].equals("Callsign:")) {
- cmd = Altos.AO_LOG_CALLSIGN;
- data = tokens[1].replaceAll("\"","");
- } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) {
- cmd = Altos.AO_LOG_ACCEL_CAL;
- a = Integer.parseInt(tokens[3]);
- b = Integer.parseInt(tokens[5]);
- } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) {
- cmd = Altos.AO_LOG_RADIO_CAL;
- a = Integer.parseInt(tokens[2]);
- } else if (tokens[0].equals("manufacturer")) {
- cmd = Altos.AO_LOG_MANUFACTURER;
- data = tokens[1];
- } else if (tokens[0].equals("product")) {
- cmd = Altos.AO_LOG_PRODUCT;
- data = tokens[1];
- } else if (tokens[0].equals("serial-number")) {
- cmd = Altos.AO_LOG_SERIAL_NUMBER;
- a = Integer.parseInt(tokens[1]);
- } else if (tokens[0].equals("software-version")) {
- cmd = Altos.AO_LOG_SOFTWARE_VERSION;
- data = tokens[1];
- } else {
+ if (tokens[0].length() == 1) {
+ if (tokens.length != 4) {
+ cmd = Altos.AO_LOG_INVALID;
+ data = line;
+ } else {
+ cmd = tokens[0].codePointAt(0);
+ tick = Integer.parseInt(tokens[1],16);
+ tick_valid = true;
+ a = Integer.parseInt(tokens[2],16);
+ b = Integer.parseInt(tokens[3],16);
+ }
+ } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) {
+ cmd = Altos.AO_LOG_CONFIG_VERSION;
+ data = tokens[2];
+ } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) {
+ cmd = Altos.AO_LOG_MAIN_DEPLOY;
+ a = Integer.parseInt(tokens[2]);
+ } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) {
+ cmd = Altos.AO_LOG_APOGEE_DELAY;
+ a = Integer.parseInt(tokens[2]);
+ } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) {
+ cmd = Altos.AO_LOG_RADIO_CHANNEL;
+ a = Integer.parseInt(tokens[2]);
+ } else if (tokens[0].equals("Callsign:")) {
+ cmd = Altos.AO_LOG_CALLSIGN;
+ data = tokens[1].replaceAll("\"","");
+ } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) {
+ cmd = Altos.AO_LOG_ACCEL_CAL;
+ a = Integer.parseInt(tokens[3]);
+ b = Integer.parseInt(tokens[5]);
+ } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) {
+ cmd = Altos.AO_LOG_RADIO_CAL;
+ a = Integer.parseInt(tokens[2]);
+ } else if (tokens[0].equals("manufacturer")) {
+ cmd = Altos.AO_LOG_MANUFACTURER;
+ data = tokens[1];
+ } else if (tokens[0].equals("product")) {
+ cmd = Altos.AO_LOG_PRODUCT;
+ data = tokens[1];
+ } else if (tokens[0].equals("serial-number")) {
+ cmd = Altos.AO_LOG_SERIAL_NUMBER;
+ a = Integer.parseInt(tokens[1]);
+ } else if (tokens[0].equals("software-version")) {
+ cmd = Altos.AO_LOG_SOFTWARE_VERSION;
+ data = tokens[1];
+ } else {
+ cmd = Altos.AO_LOG_INVALID;
+ data = line;
+ }
+ } catch (NumberFormatException ne) {
cmd = Altos.AO_LOG_INVALID;
data = line;
}
}
}
+ public AltosEepromRecord(int in_cmd, int in_tick, int in_a, int in_b) {
+ tick_valid = true;
+ cmd = in_cmd;
+ tick = in_tick;
+ a = in_a;
+ b = in_b;
+ }
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import altosui.AltosHexfile;
+
+public class AltosFlash {
+ File file;
+ FileInputStream input;
+ AltosHexfile image;
+ JFrame frame;
+ AltosDevice debug_dongle;
+ AltosDebug debug;
+ AltosRomconfig rom_config;
+ ActionListener listener;
+ boolean aborted;
+
+ static final byte MOV_direct_data = (byte) 0x75;
+ static final byte MOV_DPTR_data16 = (byte) 0x90;
+ static final byte MOV_A_data = (byte) 0x74;
+ static final byte MOVX_atDPTR_A = (byte) 0xf0;
+ static final byte MOVX_A_atDPTR = (byte) 0xe0;
+ static final byte INC_DPTR = (byte) 0xa3;
+ static final byte TRAP = (byte) 0xa5;
+
+ static final byte JB = (byte) 0x20;
+
+ static final byte MOV_A_direct = (byte) 0xe5;
+ static final byte MOV_direct1_direct2 = (byte) 0x85;
+ static final byte MOV_direct_A = (byte) 0xf5;
+ static final byte MOV_R0_data = (byte) (0x78 | 0);
+ static final byte MOV_R1_data = (byte) (0x78 | 1);
+ static final byte MOV_R2_data = (byte) (0x78 | 2);
+ static final byte MOV_R3_data = (byte) (0x78 | 3);
+ static final byte MOV_R4_data = (byte) (0x78 | 4);
+ static final byte MOV_R5_data = (byte) (0x78 | 5);
+ static final byte MOV_R6_data = (byte) (0x78 | 6);
+ static final byte MOV_R7_data = (byte) (0x78 | 7);
+ static final byte DJNZ_R0_rel = (byte) (0xd8 | 0);
+ static final byte DJNZ_R1_rel = (byte) (0xd8 | 1);
+ static final byte DJNZ_R2_rel = (byte) (0xd8 | 2);
+ static final byte DJNZ_R3_rel = (byte) (0xd8 | 3);
+ static final byte DJNZ_R4_rel = (byte) (0xd8 | 4);
+ static final byte DJNZ_R5_rel = (byte) (0xd8 | 5);
+ static final byte DJNZ_R6_rel = (byte) (0xd8 | 6);
+ static final byte DJNZ_R7_rel = (byte) (0xd8 | 7);
+
+ static final byte P1DIR = (byte) 0xFE;
+ static final byte P1 = (byte) 0x90;
+
+ /* flash controller */
+ static final byte FWT = (byte) 0xAB;
+ static final byte FADDRL = (byte) 0xAC;
+ static final byte FADDRH = (byte) 0xAD;
+ static final byte FCTL = (byte) 0xAE;
+ static final byte FCTL_BUSY = (byte) 0x80;
+ static final byte FCTL_BUSY_BIT = (byte) 7;
+ static final byte FCTL_SWBSY = (byte) 0x40;
+ static final byte FCTL_SWBSY_BIT = (byte) 6;
+ static final byte FCTL_CONTRD = (byte) 0x10;
+ static final byte FCTL_WRITE = (byte) 0x02;
+ static final byte FCTL_ERASE = (byte) 0x01;
+ static final byte FWDATA = (byte) 0xAF;
+
+ static final byte ACC = (byte) 0xE0;
+
+ /* offsets within the flash_page program */
+ static final int FLASH_ADDR_HIGH = 8;
+ static final int FLASH_ADDR_LOW = 11;
+ static final int RAM_ADDR_HIGH = 13;
+ static final int RAM_ADDR_LOW = 14;
+ static final int FLASH_WORDS_HIGH = 16;
+ static final int FLASH_WORDS_LOW = 18;
+ static final int FLASH_TIMING = 21;
+
+ /* sleep mode control */
+ static final int SLEEP = (byte) 0xbe;
+ static final int SLEEP_USB_EN = (byte) 0x80;
+ static final int SLEEP_XOSC_STB = (byte) 0x40;
+ static final int SLEEP_HFRC_STB = (byte) 0x20;
+ static final int SLEEP_RST_MASK = (byte) 0x18;
+ static final int SLEEP_RST_POWERON = (byte) 0x00;
+ static final int SLEEP_RST_EXTERNAL = (byte) 0x10;
+ static final int SLEEP_RST_WATCHDOG = (byte) 0x08;
+ static final int SLEEP_OSC_PD = (byte) 0x04;
+ static final int SLEEP_MODE_MASK = (byte) 0x03;
+ static final int SLEEP_MODE_PM0 = (byte) 0x00;
+ static final int SLEEP_MODE_PM1 = (byte) 0x01;
+ static final int SLEEP_MODE_PM2 = (byte) 0x02;
+ static final int SLEEP_MODE_PM3 = (byte) 0x03;
+
+ /* clock controller */
+ static final byte CLKCON = (byte) 0xC6;
+ static final byte CLKCON_OSC32K = (byte) 0x80;
+ static final byte CLKCON_OSC = (byte) 0x40;
+ static final byte CLKCON_TICKSPD = (byte) 0x38;
+ static final byte CLKCON_CLKSPD = (byte) 0x07;
+
+ static final byte[] flash_page_proto = {
+
+ MOV_direct_data, P1DIR, (byte) 0x02,
+ MOV_direct_data, P1, (byte) 0xFF,
+
+ MOV_direct_data, FADDRH, 0, /* FLASH_ADDR_HIGH */
+
+ MOV_direct_data, FADDRL, 0, /* FLASH_ADDR_LOW */
+
+ MOV_DPTR_data16, 0, 0, /* RAM_ADDR_HIGH, RAM_ADDR_LOW */
+
+ MOV_R7_data, 0, /* FLASH_WORDS_HIGH */
+
+ MOV_R6_data, 0, /* FLASH_WORDS_LOW */
+
+
+ MOV_direct_data, FWT, 0x20, /* FLASH_TIMING */
+
+ MOV_direct_data, FCTL, FCTL_ERASE,
+/* eraseWaitLoop: */
+ MOV_A_direct, FCTL,
+ JB, ACC|FCTL_BUSY_BIT, (byte) 0xfb,
+
+ MOV_direct_data, P1, (byte) 0xfd,
+
+ MOV_direct_data, FCTL, FCTL_WRITE,
+/* writeLoop: */
+ MOV_R5_data, 2,
+/* writeWordLoop: */
+ MOVX_A_atDPTR,
+ INC_DPTR,
+ MOV_direct_A, FWDATA,
+ DJNZ_R5_rel, (byte) 0xfa, /* writeWordLoop */
+/* writeWaitLoop: */
+ MOV_A_direct, FCTL,
+ JB, ACC|FCTL_SWBSY_BIT, (byte) 0xfb, /* writeWaitLoop */
+ DJNZ_R6_rel, (byte) 0xf1, /* writeLoop */
+ DJNZ_R7_rel, (byte) 0xef, /* writeLoop */
+
+ MOV_direct_data, P1DIR, (byte) 0x00,
+ MOV_direct_data, P1, (byte) 0xFF,
+ TRAP,
+ };
+
+ public byte[] make_flash_page(int flash_addr, int ram_addr, int byte_count) {
+ int flash_word_addr = flash_addr >> 1;
+ int flash_word_count = ((byte_count + 1) >> 1);
+
+ byte[] flash_page = new byte[flash_page_proto.length];
+ for (int i = 0; i < flash_page.length; i++)
+ flash_page[i] = flash_page_proto[i];
+
+ flash_page[FLASH_ADDR_HIGH] = (byte) (flash_word_addr >> 8);
+ flash_page[FLASH_ADDR_LOW] = (byte) (flash_word_addr);
+ flash_page[RAM_ADDR_HIGH] = (byte) (ram_addr >> 8);
+ flash_page[RAM_ADDR_LOW] = (byte) (ram_addr);
+
+ byte flash_words_low = (byte) (flash_word_count);
+ byte flash_words_high = (byte) (flash_word_count >> 8);
+ /* the flashing code has a minor 'bug' */
+ if (flash_words_low != 0)
+ flash_words_high++;
+
+ flash_page[FLASH_WORDS_HIGH] = (byte) flash_words_high;
+ flash_page[FLASH_WORDS_LOW] = (byte) flash_words_low;
+ return flash_page;
+ }
+
+ static byte[] set_clkcon_fast = {
+ MOV_direct_data, CLKCON, 0x00
+ };
+
+ static byte[] get_sleep = {
+ MOV_A_direct, SLEEP
+ };
+
+ public void clock_init() throws IOException, InterruptedException {
+ debug.debug_instr(set_clkcon_fast);
+
+ byte status;
+ for (int times = 0; times < 20; times++) {
+ Thread.sleep(1);
+ status = debug.debug_instr(get_sleep);
+ if ((status & SLEEP_XOSC_STB) != 0)
+ return;
+ }
+ throw new IOException("Failed to initialize target clock");
+ }
+
+ void action(String s, int percent) {
+ if (listener != null && !aborted)
+ listener.actionPerformed(new ActionEvent(this,
+ percent,
+ s));
+ }
+
+ void action(int part, int total) {
+ int percent = 100 * part / total;
+ action(String.format("%d/%d (%d%%)",
+ part, total, percent),
+ percent);
+ }
+
+ void run(int pc) throws IOException, InterruptedException {
+ debug.set_pc(pc);
+ int set_pc = debug.get_pc();
+ if (pc != set_pc)
+ throw new IOException("Failed to set target program counter");
+ debug.resume();
+
+ for (int times = 0; times < 20; times++) {
+ byte status = debug.read_status();
+ if ((status & AltosDebug.STATUS_CPU_HALTED) != 0)
+ return;
+ }
+
+ throw new IOException("Failed to execute program on target");
+ }
+
+ public void flash() throws IOException, FileNotFoundException, InterruptedException {
+ if (!check_rom_config())
+ throw new IOException("Invalid rom config settings");
+ if (image.address + image.data.length > 0x8000)
+ throw new IOException(String.format("Flash image too long %d",
+ image.address +
+ image.data.length));
+ if ((image.address & 0x3ff) != 0)
+ throw new IOException(String.format("Flash image must start on page boundary (is 0x%x)",
+ image.address));
+ int ram_address = 0xf000;
+ int flash_prog = 0xf400;
+
+ /*
+ * Store desired config values into image
+ */
+ rom_config.write(image);
+ /*
+ * Bring up the clock
+ */
+ clock_init();
+
+ int remain = image.data.length;
+ int flash_addr = image.address;
+ int image_start = 0;
+
+ action("start", 0);
+ action(0, image.data.length);
+ while (remain > 0 && !aborted) {
+ int this_time = remain;
+ if (this_time > 0x400)
+ this_time = 0x400;
+
+ /* write the data */
+ debug.write_memory(ram_address, image.data,
+ image_start, this_time);
+
+ /* write the flash program */
+ byte[] flash_page = make_flash_page(flash_addr,
+ ram_address,
+ this_time);
+ debug.write_memory(flash_prog, flash_page);
+
+ run(flash_prog);
+
+ byte[] check = debug.read_memory(flash_addr, this_time);
+ for (int i = 0; i < this_time; i++)
+ if (check[i] != image.data[image_start + i])
+ throw new IOException(String.format("Flash write failed at 0x%x (%02x != %02x)",
+ image.address + image_start + i,
+ check[i], image.data[image_start + i]));
+ remain -= this_time;
+ flash_addr += this_time;
+ image_start += this_time;
+
+ action(image.data.length - remain, image.data.length);
+ }
+ if (!aborted) {
+ action("done", 100);
+ debug.set_pc(image.address);
+ debug.resume();
+ }
+ debug.close();
+ }
+
+ public void abort() {
+ aborted = true;
+ debug.close();
+ }
+
+ public void addActionListener(ActionListener l) {
+ listener = l;
+ }
+
+ public boolean check_rom_config() {
+ if (rom_config == null)
+ rom_config = debug.romconfig();
+ return rom_config != null && rom_config.valid();
+ }
+
+ public void set_romconfig (AltosRomconfig romconfig) {
+ rom_config = romconfig;
+ }
+
+ public AltosRomconfig romconfig() {
+ if (!check_rom_config())
+ return null;
+ return rom_config;
+ }
+
+ public void open() throws IOException, FileNotFoundException, InterruptedException {
+ input = new FileInputStream(file);
+ image = new AltosHexfile(input);
+ debug.open(debug_dongle);
+ if (!debug.check_connection())
+ throw new IOException("Debug port not connected");
+ }
+
+ public AltosFlash(File in_file, AltosDevice in_debug_dongle) {
+ file = in_file;
+ debug_dongle = in_debug_dongle;
+ debug = new AltosDebug();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import altosui.AltosHexfile;
+import altosui.AltosFlash;
+
+public class AltosFlashUI
+ extends JDialog
+ implements Runnable, ActionListener
+{
+ Container pane;
+ Box box;
+ JLabel serial_label;
+ JLabel serial_value;
+ JLabel file_label;
+ JLabel file_value;
+ JProgressBar pbar;
+ JButton cancel;
+
+ File file;
+ Thread thread;
+ JFrame frame;
+ AltosDevice debug_dongle;
+ AltosFlash flash;
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == cancel) {
+ abort();
+ dispose();
+ } else {
+ String cmd = e.getActionCommand();
+ if (cmd.equals("done"))
+ ;
+ else if (cmd.equals("start")) {
+ setVisible(true);
+ } else {
+ pbar.setValue(e.getID());
+ pbar.setString(cmd);
+ }
+ }
+ }
+
+ public void run() {
+ flash = new AltosFlash(file, debug_dongle);
+ flash.addActionListener(this);
+ try {
+ flash.open();
+ AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame);
+
+ romconfig_ui.set(flash.romconfig());
+ AltosRomconfig romconfig = romconfig_ui.showDialog();
+
+ if (romconfig != null && romconfig.valid()) {
+ flash.set_romconfig(romconfig);
+ serial_value.setText(String.format("%d",
+ flash.romconfig().serial_number));
+ file_value.setText(file.toString());
+ setVisible(true);
+ flash.flash();
+ flash = null;
+ }
+ } catch (FileNotFoundException ee) {
+ JOptionPane.showMessageDialog(frame,
+ "Cannot open image",
+ file.toString(),
+ JOptionPane.ERROR_MESSAGE);
+ } catch (IOException e) {
+ JOptionPane.showMessageDialog(frame,
+ e.getMessage(),
+ file.toString(),
+ JOptionPane.ERROR_MESSAGE);
+ } catch (InterruptedException ie) {
+ } finally {
+ abort();
+ }
+ dispose();
+ }
+
+ public void abort() {
+ if (flash != null)
+ flash.abort();
+ }
+
+ public void build_dialog() {
+ GridBagConstraints c;
+ Insets il = new Insets(4,4,4,4);
+ Insets ir = new Insets(4,4,4,4);
+
+ pane = getContentPane();
+ pane.setLayout(new GridBagLayout());
+
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 0;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ serial_label = new JLabel("Serial:");
+ pane.add(serial_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 1; c.gridy = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ serial_value = new JLabel("");
+ pane.add(serial_value, c);
+
+ c = new GridBagConstraints();
+ c.fill = GridBagConstraints.NONE;
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ file_label = new JLabel("File:");
+ pane.add(file_label, c);
+
+ c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.gridx = 1; c.gridy = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ file_value = new JLabel("");
+ pane.add(file_value, c);
+
+ pbar = new JProgressBar();
+ pbar.setMinimum(0);
+ pbar.setMaximum(100);
+ pbar.setValue(0);
+ pbar.setString("");
+ pbar.setStringPainted(true);
+ pbar.setPreferredSize(new Dimension(600, 20));
+ c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.CENTER;
+ c.gridx = 0; c.gridy = 2;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ Insets ib = new Insets(4,4,4,4);
+ c.insets = ib;
+ pane.add(pbar, c);
+
+ cancel = new JButton("Cancel");
+ c = new GridBagConstraints();
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.gridx = 0; c.gridy = 3;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ Insets ic = new Insets(4,4,4,4);
+ c.insets = ic;
+ pane.add(cancel, c);
+ cancel.addActionListener(this);
+ pack();
+ setLocationRelativeTo(frame);
+ }
+
+ public AltosFlashUI(JFrame in_frame) {
+ super(in_frame, "Program Altusmetrum Device", false);
+
+ frame = in_frame;
+
+ build_dialog();
+
+ debug_dongle = AltosDeviceDialog.show(frame, AltosDevice.Any);
+
+ if (debug_dongle == null)
+ return;
+
+ JFileChooser hexfile_chooser = new JFileChooser();
+
+ hexfile_chooser.setDialogTitle("Select Flash Image");
+ hexfile_chooser.setFileFilter(new FileNameExtensionFilter("Flash Image", "ihx"));
+ int returnVal = hexfile_chooser.showOpenDialog(frame);
+
+ if (returnVal != JFileChooser.APPROVE_OPTION)
+ return;
+
+ file = hexfile_chooser.getSelectedFile();
+
+ thread = new Thread(this);
+ thread.start();
+ }
+}
\ No newline at end of file
AltosGPSSat[] cc_gps_sat; /* tracking data */
- void ParseGPSTime(String date, String time) throws ParseException {
+ void ParseGPSDate(String date) throws ParseException {
String[] ymd = date.split("-");
if (ymd.length != 3)
throw new ParseException("error parsing GPS date " + date + " got " + ymd.length, 0);
year = AltosParse.parse_int(ymd[0]);
month = AltosParse.parse_int(ymd[1]);
day = AltosParse.parse_int(ymd[2]);
+ }
+ void ParseGPSTime(String time) throws ParseException {
String[] hms = time.split(":");
if (hms.length != 3)
throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0);
hour = minute = second = 0;
}
- public AltosGPS(String[] words, int i) throws ParseException {
+ public AltosGPS(String[] words, int i, int version) throws ParseException {
AltosParse.word(words[i++], "GPS");
nsat = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "sat");
locked = true;
connected = true;
- ParseGPSTime(words[i], words[i+1]); i += 2;
+ if (version > 1)
+ ParseGPSDate(words[i++]);
+ else
+ year = month = day = 0;
+ ParseGPSTime(words[i++]);
lat = AltosParse.parse_coord(words[i++]);
lon = AltosParse.parse_coord(words[i++]);
- alt = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "m"));
- ground_speed = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(H)"));
- course = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "°"));
- climb_rate = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(V)"));
- hdop = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "(hdop)"));
- h_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(herr)"));
- v_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(verr)"));
+ alt = AltosParse.parse_int(words[i++]);
+ if (version > 1 || (i < words.length && !words[i].equals("SAT"))) {
+ ground_speed = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(H)"));
+ course = AltosParse.parse_int(words[i++]);
+ climb_rate = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(V)"));
+ hdop = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "(hdop)"));
+ h_error = AltosParse.parse_int(words[i++]);
+ v_error = AltosParse.parse_int(words[i++]);
+ }
} else {
i++;
}
- AltosParse.word(words[i++], "SAT");
- int tracking_channels = 0;
- if (words[i].equals("not-connected"))
- tracking_channels = 0;
- else
- tracking_channels = AltosParse.parse_int(words[i]);
- i++;
- cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels];
- for (int chan = 0; chan < tracking_channels; chan++) {
- cc_gps_sat[chan] = new AltosGPS.AltosGPSSat();
- cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]);
- cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]);
- }
+ if (i < words.length) {
+ AltosParse.word(words[i++], "SAT");
+ int tracking_channels = 0;
+ if (words[i].equals("not-connected"))
+ tracking_channels = 0;
+ else
+ tracking_channels = AltosParse.parse_int(words[i]);
+ i++;
+ cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels];
+ for (int chan = 0; chan < tracking_channels; chan++) {
+ cc_gps_sat[chan] = new AltosGPS.AltosGPSSat();
+ cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]);
+ /* Older versions included SiRF status bits */
+ if (version < 2)
+ i++;
+ cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]);
+ }
+ } else
+ cc_gps_sat = new AltosGPS.AltosGPSSat[0];
}
public void set_latitude(int in_lat) {
nsat = old.nsat;
locked = old.locked;
connected = old.connected;
+ date_valid = old.date_valid;
lat = old.lat; /* degrees (+N -S) */
lon = old.lon; /* degrees (+E -W) */
alt = old.alt; /* m */
package altosui;
+import altosui.AltosGPS;
+
import java.lang.Math;
public class AltosGreatCircle {
static final double rad = Math.PI / 180;
static final double earth_radius = 6371.2 * 1000; /* in meters */
- AltosGreatCircle (double start_lat, double start_lon,
- double end_lat, double end_lon)
+ public AltosGreatCircle (double start_lat, double start_lon,
+ double end_lat, double end_lon)
{
double lat1 = rad * start_lat;
double lon1 = rad * -start_lon;
distance = d * earth_radius;
bearing = course * 180/Math.PI;
}
+
+ public AltosGreatCircle(AltosGPS start, AltosGPS end) {
+ this(start.lat, start.lon, end.lat, end.lon);
+ }
+
+ public AltosGreatCircle() {
+ distance = 0;
+ bearing = 0;
+ }
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.lang.*;
+import java.io.*;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.LinkedList;
+import java.util.Iterator;
+import java.util.Arrays;
+
+class HexFileInputStream extends PushbackInputStream {
+ public int line;
+
+ public HexFileInputStream(FileInputStream o) {
+ super(new BufferedInputStream(o));
+ line = 1;
+ }
+
+ public int read() throws IOException {
+ int c = super.read();
+ if (c == '\n')
+ line++;
+ return c;
+ }
+
+ public void unread(int c) throws IOException {
+ if (c == '\n')
+ line--;
+ if (c != -1)
+ super.unread(c);
+ }
+}
+
+class HexRecord implements Comparable {
+ public int address;
+ public int type;
+ public byte checksum;
+ public byte[] data;
+
+ static final int NORMAL = 0;
+ static final int EOF = 1;
+ static final int EXTENDED_ADDRESS = 2;
+
+ enum read_state {
+ marker,
+ length,
+ address,
+ type,
+ data,
+ checksum,
+ newline,
+ white,
+ done,
+ }
+
+ boolean ishex(int c) {
+ if ('0' <= c && c <= '9')
+ return true;
+ if ('a' <= c && c <= 'f')
+ return true;
+ if ('A' <= c && c <= 'F')
+ return true;
+ return false;
+ }
+
+ boolean isspace(int c) {
+ switch (c) {
+ case ' ':
+ case '\t':
+ return true;
+ }
+ return false;
+ }
+
+ int fromhex(int c) {
+ if ('0' <= c && c <= '9')
+ return c - '0';
+ if ('a' <= c && c <= 'f')
+ return c - 'a' + 10;
+ if ('A' <= c && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+ }
+
+ public byte checksum() {
+ byte got = 0;
+
+ got += data.length;
+ got += (address >> 8) & 0xff;
+ got += (address ) & 0xff;
+ got += type;
+ for (int i = 0; i < data.length; i++)
+ got += data[i];
+ return (byte) (-got);
+ }
+
+ public int compareTo(Object other) {
+ HexRecord o = (HexRecord) other;
+ return address - o.address;
+ }
+
+ public String toString() {
+ return String.format("%04x: %02x (%d)", address, type, data.length);
+ }
+
+ public HexRecord(HexFileInputStream input) throws IOException {
+ read_state state = read_state.marker;
+ int nhexbytes = 0;
+ int hex = 0;
+ int ndata = 0;
+ byte got_checksum;
+
+ while (state != read_state.done) {
+ int c = input.read();
+ if (c < 0 && state != read_state.white)
+ throw new IOException(String.format("%d: Unexpected EOF", input.line));
+ if (c == ' ')
+ continue;
+ switch (state) {
+ case marker:
+ if (c != ':')
+ throw new IOException("Missing ':'");
+ state = read_state.length;
+ nhexbytes = 2;
+ hex = 0;
+ break;
+ case length:
+ case address:
+ case type:
+ case data:
+ case checksum:
+ if(!ishex(c))
+ throw new IOException(String.format("Non-hex char '%c'", c));
+ hex = hex << 4 | fromhex(c);
+ --nhexbytes;
+ if (nhexbytes != 0)
+ break;
+
+ switch (state) {
+ case length:
+ data = new byte[hex];
+ state = read_state.address;
+ nhexbytes = 4;
+ break;
+ case address:
+ address = hex;
+ state = read_state.type;
+ nhexbytes = 2;
+ break;
+ case type:
+ type = hex;
+ if (data.length > 0)
+ state = read_state.data;
+ else
+ state = read_state.checksum;
+ nhexbytes = 2;
+ ndata = 0;
+ break;
+ case data:
+ data[ndata] = (byte) hex;
+ ndata++;
+ nhexbytes = 2;
+ if (ndata == data.length)
+ state = read_state.checksum;
+ break;
+ case checksum:
+ checksum = (byte) hex;
+ state = read_state.newline;
+ break;
+ default:
+ break;
+ }
+ hex = 0;
+ break;
+ case newline:
+ if (c != '\n' && c != '\r')
+ throw new IOException("Missing newline");
+ state = read_state.white;
+ break;
+ case white:
+ if (!isspace(c)) {
+ input.unread(c);
+ state = read_state.done;
+ }
+ break;
+ case done:
+ break;
+ }
+ }
+ got_checksum = checksum();
+ if (got_checksum != checksum)
+ throw new IOException(String.format("Invalid checksum (read 0x%02x computed 0x%02x)\n",
+ checksum, got_checksum));
+ }
+}
+
+public class AltosHexfile {
+ public int address;
+ public byte[] data;
+
+ public byte get_byte(int a) {
+ return data[a - address];
+ }
+
+ public AltosHexfile(FileInputStream file) throws IOException {
+ HexFileInputStream input = new HexFileInputStream(file);
+ LinkedList<HexRecord> record_list = new LinkedList<HexRecord>();
+ boolean done = false;
+
+ while (!done) {
+ HexRecord record = new HexRecord(input);
+
+ if (record.type == HexRecord.EOF)
+ done = true;
+ else
+ record_list.add(record);
+ }
+ HexRecord[] records = record_list.toArray(new HexRecord[0]);
+ Arrays.sort(records);
+ if (records.length > 0) {
+ int base = records[0].address;
+ int bound = records[records.length-1].address +
+ records[records.length-1].data.length;
+
+ data = new byte[bound - base];
+ address = base;
+ Arrays.fill(data, (byte) 0xff);
+
+ /* Paint the records into the new array */
+ for (int i = 0; i < records.length; i++) {
+ for (int j = 0; j < records[i].data.length; j++)
+ data[records[i].address - base + j] = records[i].data[j];
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+public class AltosLine {
+ public String line;
+
+ public AltosLine() {
+ line = null;
+ }
+
+ public AltosLine(String s) {
+ line = s;
+ }
+}
\ No newline at end of file
import java.util.concurrent.LinkedBlockingQueue;
import altosui.AltosSerial;
import altosui.AltosFile;
+import altosui.AltosLine;
/*
* This creates a thread to capture telemetry data and write it to
*/
class AltosLog implements Runnable {
- LinkedBlockingQueue<String> input_queue;
+ LinkedBlockingQueue<AltosLine> input_queue;
LinkedBlockingQueue<String> pending_queue;
int serial;
int flight;
public void run () {
try {
for (;;) {
- String line = input_queue.take();
+ AltosLine line = input_queue.take();
+ if (line.line == null)
+ continue;
try {
- AltosTelemetry telem = new AltosTelemetry(line);
+ AltosTelemetry telem = new AltosTelemetry(line.line);
if (telem.serial != serial || telem.flight != flight || log_file == null) {
close();
serial = telem.serial;
open(telem);
}
} catch (ParseException pe) {
+ } catch (AltosCRCException ce) {
}
if (log_file != null) {
- log_file.write(line);
+ log_file.write(line.line);
log_file.write('\n');
log_file.flush();
} else
- pending_queue.put(line);
+ pending_queue.put(line.line);
}
} catch (InterruptedException ie) {
} catch (IOException ie) {
public AltosLog (AltosSerial s) {
pending_queue = new LinkedBlockingQueue<String> ();
- input_queue = new LinkedBlockingQueue<String> ();
+ input_queue = new LinkedBlockingQueue<AltosLine> ();
s.add_monitor(input_queue);
serial = -1;
flight = -1;
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+
+import altosui.AltosPreferences;
+import altosui.AltosReader;
+import altosui.AltosEepromReader;
+import altosui.AltosTelemetryReader;
+
+public class AltosLogfileChooser extends JFileChooser {
+ JFrame frame;
+ String filename;
+ File file;
+
+ public String filename() {
+ return filename;
+ }
+
+ public File file() {
+ return file;
+ }
+
+ public AltosReader runDialog() {
+ int ret;
+
+ ret = showOpenDialog(frame);
+ if (ret == APPROVE_OPTION) {
+ file = getSelectedFile();
+ if (file == null)
+ return null;
+ filename = file.getName();
+ try {
+ FileInputStream in;
+
+ in = new FileInputStream(file);
+ if (filename.endsWith("eeprom"))
+ return new AltosEepromReader(in);
+ else
+ return new AltosTelemetryReader(in);
+ } catch (FileNotFoundException fe) {
+ JOptionPane.showMessageDialog(frame,
+ filename,
+ "Cannot open file",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ return null;
+ }
+
+ public AltosLogfileChooser(JFrame in_frame) {
+ frame = in_frame;
+ setDialogTitle("Select Flight Record File");
+ setFileFilter(new FileNameExtensionFilter("Flight data file",
+ "eeprom",
+ "telem"));
+ setCurrentDirectory(AltosPreferences.logdir());
+ }
+}
\ No newline at end of file
import java.text.*;
import java.lang.*;
+import altosui.Altos;
+
public class AltosParse {
+ static boolean isdigit(char c) {
+ return '0' <= c && c <= '9';
+ }
+
static int parse_int(String v) throws ParseException {
try {
- return Integer.parseInt(v);
+ return Altos.fromdec(v);
} catch (NumberFormatException e) {
throw new ParseException("error parsing int " + v, 0);
}
static int parse_hex(String v) throws ParseException {
try {
- return Integer.parseInt(v, 16);
+ return Altos.fromhex(v);
} catch (NumberFormatException e) {
throw new ParseException("error parsing hex " + v, 0);
}
public class AltosReader {
public AltosRecord read() throws IOException, ParseException { return null; }
+ public void close() { }
+ public void write_comments(PrintStream out) { }
}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+import java.io.*;
+import altosui.AltosHexfile;
+
+public class AltosRomconfig {
+ public boolean valid;
+ public int version;
+ public int check;
+ public int serial_number;
+ public int radio_calibration;
+
+ static int get_int(byte[] bytes, int start, int len) {
+ int v = 0;
+ int o = 0;
+ while (len > 0) {
+ v = v | ((((int) bytes[start]) & 0xff) << o);
+ start++;
+ len--;
+ o += 8;
+ }
+ return v;
+ }
+
+ static void put_int(int value, byte[] bytes, int start, int len) {
+ while (len > 0) {
+ bytes[start] = (byte) (value & 0xff);
+ start++;
+ len--;
+ value >>= 8;
+ }
+ }
+
+ static void put_string(String value, byte[] bytes, int start) {
+ for (int i = 0; i < value.length(); i++)
+ bytes[start + i] = (byte) value.charAt(i);
+ }
+
+ static final int AO_USB_DESC_STRING = 3;
+
+ static void put_usb_serial(int value, byte[] bytes, int start) {
+ int offset = start + 0xa;
+ int string_num = 0;
+
+ while (offset < bytes.length && bytes[offset] != 0) {
+ if (bytes[offset + 1] == AO_USB_DESC_STRING) {
+ ++string_num;
+ if (string_num == 4)
+ break;
+ }
+ offset += ((int) bytes[offset]) & 0xff;
+ }
+ if (offset >= bytes.length || bytes[offset] == 0)
+ return;
+ int len = ((((int) bytes[offset]) & 0xff) - 2) / 2;
+ String fmt = String.format("%%0%dd", len);
+
+ String s = String.format(fmt, value);
+ if (s.length() != len) {
+ System.out.printf("weird usb length issue %s isn't %d\n",
+ s, len);
+ return;
+ }
+ for (int i = 0; i < len; i++) {
+ bytes[offset + 2 + i*2] = (byte) s.charAt(i);
+ bytes[offset + 2 + i*2+1] = 0;
+ }
+ }
+
+ public AltosRomconfig(byte[] bytes, int offset) {
+ version = get_int(bytes, offset + 0, 2);
+ check = get_int(bytes, offset + 2, 2);
+ if (check == (~version & 0xffff)) {
+ switch (version) {
+ case 2:
+ case 1:
+ serial_number = get_int(bytes, offset + 4, 2);
+ radio_calibration = get_int(bytes, offset + 6, 4);
+ valid = true;
+ break;
+ }
+ }
+ }
+
+ public AltosRomconfig(AltosHexfile hexfile) {
+ this(hexfile.data, 0xa0 - hexfile.address);
+ }
+
+ public void write(byte[] bytes, int offset) throws IOException {
+ if (!valid)
+ throw new IOException("rom configuration invalid");
+
+ if (offset < 0 || bytes.length < offset + 10)
+ throw new IOException("image cannot contain rom config");
+
+ AltosRomconfig existing = new AltosRomconfig(bytes, offset);
+ if (!existing.valid)
+ throw new IOException("image does not contain existing rom config");
+
+ switch (existing.version) {
+ case 2:
+ put_usb_serial(serial_number, bytes, offset);
+ case 1:
+ put_int(serial_number, bytes, offset + 4, 2);
+ put_int(radio_calibration, bytes, offset + 6, 4);
+ break;
+ }
+ }
+
+ public void write (AltosHexfile hexfile) throws IOException {
+ write(hexfile.data, 0xa0 - hexfile.address);
+ AltosRomconfig check = new AltosRomconfig(hexfile);
+ if (!check.valid())
+ throw new IOException("writing new rom config failed\n");
+ }
+
+ public AltosRomconfig(int in_serial_number, int in_radio_calibration) {
+ valid = true;
+ version = 1;
+ check = (~version & 0xffff);
+ serial_number = in_serial_number;
+ radio_calibration = in_radio_calibration;
+ }
+
+ public boolean valid() {
+ return valid && serial_number != 0;
+ }
+
+ public AltosRomconfig() {
+ valid = false;
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import javax.swing.event.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+
+import altosui.AltosRomconfig;
+
+public class AltosRomconfigUI
+ extends JDialog
+ implements ActionListener
+{
+ Container pane;
+ Box box;
+ JLabel serial_label;
+ JLabel radio_calibration_label;
+
+ JFrame owner;
+ JTextField serial_value;
+ JTextField radio_calibration_value;
+
+ JButton ok;
+ JButton cancel;
+
+ /* Build the UI using a grid bag */
+ public AltosRomconfigUI(JFrame in_owner) {
+ super (in_owner, "Configure TeleMetrum Rom Values", true);
+
+ owner = in_owner;
+ GridBagConstraints c;
+
+ Insets il = new Insets(4,4,4,4);
+ Insets ir = new Insets(4,4,4,4);
+
+ pane = getContentPane();
+ pane.setLayout(new GridBagLayout());
+
+ /* Serial */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 0;
+ c.gridwidth = 3;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ serial_label = new JLabel("Serial:");
+ pane.add(serial_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 3; c.gridy = 0;
+ c.gridwidth = 3;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ serial_value = new JTextField("0");
+ pane.add(serial_value, c);
+
+ /* Radio calibration value */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 1;
+ c.gridwidth = 3;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ c.ipady = 5;
+ radio_calibration_label = new JLabel("Radio Calibration:");
+ pane.add(radio_calibration_label, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 3; c.gridy = 1;
+ c.gridwidth = 3;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = ir;
+ c.ipady = 5;
+ radio_calibration_value = new JTextField("1186611");
+ pane.add(radio_calibration_value, c);
+
+ /* Buttons */
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 2;
+ c.gridwidth = 3;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = il;
+ ok = new JButton("OK");
+ pane.add(ok, c);
+ ok.addActionListener(this);
+ ok.setActionCommand("ok");
+
+ c = new GridBagConstraints();
+ c.gridx = 3; c.gridy = 2;
+ c.gridwidth = 3;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = il;
+ cancel = new JButton("Cancel");
+ pane.add(cancel, c);
+ cancel.addActionListener(this);
+ cancel.setActionCommand("cancel");
+
+ pack();
+ setLocationRelativeTo(owner);
+ }
+
+ boolean selected;
+
+ /* Listen for events from our buttons */
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+
+ if (cmd.equals("ok")) {
+ AltosRomconfig romconfig = romconfig();
+ if (romconfig == null || !romconfig.valid()) {
+ JOptionPane.showMessageDialog(this,
+ "Invalid serial number or radio calibration value",
+ "Invalid rom configuration",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ selected = true;
+ }
+ setVisible(false);
+ }
+
+ int serial() {
+ return Integer.parseInt(serial_value.getText());
+ }
+
+ void set_serial(int serial) {
+ serial_value.setText(String.format("%d", serial));
+ }
+
+ int radio_calibration() {
+ return Integer.parseInt(radio_calibration_value.getText());
+ }
+
+ void set_radio_calibration(int calibration) {
+ radio_calibration_value.setText(String.format("%d", calibration));
+ }
+
+ public void set(AltosRomconfig config) {
+ if (config != null && config.valid()) {
+ set_serial(config.serial_number);
+ set_radio_calibration(config.radio_calibration);
+ }
+ }
+
+ AltosRomconfig romconfig() {
+ try {
+ return new AltosRomconfig(serial(), radio_calibration());
+ } catch (NumberFormatException ne) {
+ return null;
+ }
+ }
+
+ public AltosRomconfig showDialog() {
+ setVisible(true);
+ if (selected)
+ return romconfig();
+ return null;
+ }
+}
import java.util.LinkedList;
import java.util.Iterator;
import altosui.AltosSerialMonitor;
+import altosui.AltosLine;
import libaltosJNI.libaltos;
import libaltosJNI.altos_device;
import libaltosJNI.SWIGTYPE_p_altos_file;
import libaltosJNI.SWIGTYPE_p_altos_list;
+import libaltosJNI.libaltosConstants;
/*
* This class reads from the serial port and places each received
public class AltosSerial implements Runnable {
SWIGTYPE_p_altos_file altos;
- LinkedList<LinkedBlockingQueue<String>> monitors;
- LinkedBlockingQueue<String> reply_queue;
+ LinkedList<LinkedBlockingQueue<AltosLine>> monitors;
+ LinkedBlockingQueue<AltosLine> reply_queue;
Thread input_thread;
String line;
+ byte[] line_bytes;
+ int line_count;
+ boolean monitor_mode;
public void run () {
int c;
c = libaltos.altos_getchar(altos, 0);
if (Thread.interrupted())
break;
- if (c == -1)
+ if (c == libaltosConstants.LIBALTOS_ERROR) {
+ for (int e = 0; e < monitors.size(); e++) {
+ LinkedBlockingQueue<AltosLine> q = monitors.get(e);
+ q.put(new AltosLine());
+ }
+ reply_queue.put (new AltosLine());
+ break;
+ }
+ if (c == libaltosConstants.LIBALTOS_TIMEOUT)
continue;
if (c == '\r')
continue;
synchronized(this) {
if (c == '\n') {
- if (line != "") {
- if (line.startsWith("VERSION")) {
+ if (line_count != 0) {
+ try {
+ line = new String(line_bytes, 0, line_count, "UTF-8");
+ } catch (UnsupportedEncodingException ue) {
+ line = "";
+ for (int i = 0; i < line_count; i++)
+ line = line + line_bytes[i];
+ }
+ if (line.startsWith("VERSION") || line.startsWith("CRC")) {
for (int e = 0; e < monitors.size(); e++) {
- LinkedBlockingQueue<String> q = monitors.get(e);
- q.put(line);
+ LinkedBlockingQueue<AltosLine> q = monitors.get(e);
+ q.put(new AltosLine (line));
}
- } else
- reply_queue.put(line);
+ } else {
+// System.out.printf("GOT: %s\n", line);
+ reply_queue.put(new AltosLine (line));
+ }
+ line_count = 0;
line = "";
}
} else {
- line = line + (char) c;
+ if (line_bytes == null) {
+ line_bytes = new byte[256];
+ } else if (line_count == line_bytes.length) {
+ byte[] new_line_bytes = new byte[line_count * 2];
+ System.arraycopy(line_bytes, 0, new_line_bytes, 0, line_count);
+ line_bytes = new_line_bytes;
+ }
+ line_bytes[line_count] = (byte) c;
+ line_count++;
}
}
}
}
}
+ public void flush_output() {
+ if (altos != null)
+ libaltos.altos_flush(altos);
+ }
+
+ public void flush_input() {
+ flush_output();
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException ie) {
+ }
+ synchronized(this) {
+ if (!"VERSION".startsWith(line) &&
+ !line.startsWith("VERSION"))
+ line = "";
+ reply_queue.clear();
+ }
+ }
+
public String get_reply() throws InterruptedException {
- return reply_queue.take();
+ flush_output();
+ AltosLine line = reply_queue.take();
+ return line.line;
}
- public void add_monitor(LinkedBlockingQueue<String> q) {
+ public void add_monitor(LinkedBlockingQueue<AltosLine> q) {
+ set_monitor(true);
monitors.add(q);
}
- public void remove_monitor(LinkedBlockingQueue<String> q) {
+ public void remove_monitor(LinkedBlockingQueue<AltosLine> q) {
monitors.remove(q);
- }
-
- public void flush () {
- synchronized(this) {
- if (!"VERSION".startsWith(line) && !line.startsWith("VERSION"))
- line = "";
- reply_queue.clear();
- }
+ if (monitors.isEmpty())
+ set_monitor(false);
}
public boolean opened() {
}
public void close() {
- if (altos != null)
+ if (altos != null) {
libaltos.altos_close(altos);
+ }
if (input_thread != null) {
try {
input_thread.interrupt();
}
public void print(String data) {
+// System.out.printf("\"%s\" ", data);
for (int i = 0; i < data.length(); i++)
putc(data.charAt(i));
}
throw new FileNotFoundException(device.getPath());
input_thread = new Thread(this);
input_thread.start();
- print("\nE 0\n");
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- }
- flush();
+ print("~\nE 0\n");
+ flush_output();
+ set_monitor(monitor_mode);
}
public void set_channel(int channel) {
- if (altos != null)
- printf("m 0\nc r %d\nm 1\n", channel);
+ if (altos != null) {
+ if (monitor_mode)
+ printf("m 0\nc r %d\nm 1\n", channel);
+ else
+ printf("c r %d\n", channel);
+ flush_output();
+ }
+ }
+
+ void set_monitor(boolean monitor) {
+ monitor_mode = monitor;
+ if (altos != null) {
+ if (monitor)
+ printf("m 1\n");
+ else
+ printf("m 0\n");
+ flush_output();
+ }
}
public void set_callsign(String callsign) {
- if (altos != null)
+ if (altos != null) {
printf ("c c %s\n", callsign);
+ flush_output();
+ }
}
public AltosSerial() {
altos = null;
input_thread = null;
line = "";
- monitors = new LinkedList<LinkedBlockingQueue<String>> ();
- reply_queue = new LinkedBlockingQueue<String> ();
+ monitor_mode = false;
+ monitors = new LinkedList<LinkedBlockingQueue<AltosLine>> ();
+ reply_queue = new LinkedBlockingQueue<AltosLine> ();
}
}
boolean gps_ready;
AltosGreatCircle from_pad;
+ double elevation; /* from pad */
+ double range; /* total distance */
double gps_height;
}
if (state == Altos.ao_flight_pad) {
- if (data.gps == null)
- System.out.printf("on pad, gps null\n");
- else
- System.out.printf ("on pad gps lat %f lon %f locked %d nsat %d\n",
- data.gps.lat, data.gps.lon, data.gps.locked ? 1 : 0, data.gps.nsat);
- if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) {
+ if (data.gps != null && data.gps.locked) {
npad++;
if (npad > 1) {
/* filter pad position */
if (data.gps != null) {
if (gps == null || !gps.locked || data.gps.locked)
gps = data.gps;
- if (npad > 0 && gps.locked)
+ if (npad > 0 && gps.locked) {
from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon);
+ }
}
+ elevation = 0;
+ range = -1;
if (npad > 0) {
gps_height = gps.alt - pad_alt;
+ if (from_pad != null) {
+ elevation = Math.atan2(height, from_pad.distance) * 180 / Math.PI;
+ range = Math.sqrt(height * height + from_pad.distance * from_pad.distance);
+ }
} else {
gps_height = 0;
}
import altosui.AltosConvert;
import altosui.AltosRecord;
import altosui.AltosGPS;
+import altosui.AltosCRCException;
/*
* Telemetry data contents
*/
public class AltosTelemetry extends AltosRecord {
- public AltosTelemetry(String line) throws ParseException {
+ public AltosTelemetry(String line) throws ParseException, AltosCRCException {
String[] words = line.split("\\s+");
int i = 0;
- AltosParse.word (words[i++], "VERSION");
- version = AltosParse.parse_int(words[i++]);
+ if (words[i].equals("CRC") && words[i+1].equals("INVALID")) {
+ i += 2;
+ AltosParse.word(words[i++], "RSSI");
+ rssi = AltosParse.parse_int(words[i++]);
+ throw new AltosCRCException(rssi);
+ }
+ if (words[i].equals("CALL")) {
+ version = 0;
+ } else {
+ AltosParse.word (words[i++], "VERSION");
+ version = AltosParse.parse_int(words[i++]);
+ }
AltosParse.word (words[i++], "CALL");
callsign = words[i++];
AltosParse.word (words[i++], "SERIAL");
serial = AltosParse.parse_int(words[i++]);
- AltosParse.word (words[i++], "FLIGHT");
- flight = AltosParse.parse_int(words[i++]);
+ if (version >= 2) {
+ AltosParse.word (words[i++], "FLIGHT");
+ flight = AltosParse.parse_int(words[i++]);
+ } else
+ flight = 0;
AltosParse.word(words[i++], "RSSI");
rssi = AltosParse.parse_int(words[i++]);
+ /* Older telemetry data had mis-computed RSSI value */
+ if (version <= 2)
+ rssi = (rssi + 74) / 2 - 74;
+
AltosParse.word(words[i++], "STATUS");
status = AltosParse.parse_hex(words[i++]);
AltosParse.word(words[i++], "gp:");
ground_pres = AltosParse.parse_int(words[i++]);
- AltosParse.word(words[i++], "a+:");
- accel_plus_g = AltosParse.parse_int(words[i++]);
+ if (version >= 1) {
+ AltosParse.word(words[i++], "a+:");
+ accel_plus_g = AltosParse.parse_int(words[i++]);
- AltosParse.word(words[i++], "a-:");
- accel_minus_g = AltosParse.parse_int(words[i++]);
+ AltosParse.word(words[i++], "a-:");
+ accel_minus_g = AltosParse.parse_int(words[i++]);
+ } else {
+ accel_plus_g = ground_accel;
+ accel_minus_g = ground_accel + 530;
+ }
- gps = new AltosGPS(words, i);
+ gps = new AltosGPS(words, i, version);
}
}
try {
for (;;) {
String line = AltosRecord.gets(input);
- if (line == null)
+ if (line == null) {
break;
- AltosTelemetry record = new AltosTelemetry(line);
- if (record == null)
- break;
- if (!saw_boost && record.state >= Altos.ao_flight_boost)
- {
- saw_boost = true;
- boost_tick = record.tick;
}
- records.add(record);
+ try {
+ AltosTelemetry record = new AltosTelemetry(line);
+ if (record == null)
+ break;
+ if (!saw_boost && record.state >= Altos.ao_flight_boost)
+ {
+ saw_boost = true;
+ boost_tick = record.tick;
+ }
+ records.add(record);
+ } catch (ParseException pe) {
+ System.out.printf("parse exception %s\n", pe.getMessage());
+ } catch (AltosCRCException ce) {
+ System.out.printf("crc error\n");
+ }
}
} catch (IOException io) {
- } catch (ParseException pe) {
+ System.out.printf("io exception\n");
}
record_iterator = records.iterator();
try {
import altosui.AltosFlightStatusTableModel;
import altosui.AltosFlightInfoTableModel;
import altosui.AltosChannelMenu;
+import altosui.AltosFlashUI;
+import altosui.AltosLogfileChooser;
+import altosui.AltosCSVUI;
+import altosui.AltosLine;
import libaltosJNI.*;
String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
Object[][] statusData = { { "0", "pad", "-50", "0" } };
+ java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
+ if (imgURL != null)
+ setIconImage(new ImageIcon(imgURL).getImage());
+
AltosPreferences.init(this);
vbox = Box.createVerticalBox();
flightInfoModel[i].finish();
}
- public void show(AltosState state) {
+ public void show(AltosState state, int crc_errors) {
+ if (state == null)
+ return;
flightStatusModel.set(state);
info_reset();
- if (state.gps_ready)
- info_add_row(0, "Ground state", "%s", "ready");
- else
- info_add_row(0, "Ground state", "wait (%d)",
- state.gps_waiting);
info_add_row(0, "Rocket state", "%s", state.data.state());
info_add_row(0, "Callsign", "%s", state.data.callsign);
info_add_row(0, "Rocket serial", "%6d", state.data.serial);
info_add_row(0, "Rocket flight", "%6d", state.data.flight);
info_add_row(0, "RSSI", "%6d dBm", state.data.rssi);
+ info_add_row(0, "CRC Errors", "%6d", crc_errors);
info_add_row(0, "Height", "%6.0f m", state.height);
info_add_row(0, "Max height", "%6.0f m", state.max_height);
info_add_row(0, "Acceleration", "%8.1f m/s²", state.acceleration);
if (state.gps == null) {
info_add_row(1, "GPS", "not available");
} else {
+ if (state.gps_ready)
+ info_add_row(1, "GPS state", "%s", "ready");
+ else
+ info_add_row(1, "GPS state", "wait (%d)",
+ state.gps_waiting);
if (state.data.gps.locked)
info_add_row(1, "GPS", " locked");
else if (state.data.gps.connected)
if (state.npad > 0) {
if (state.from_pad != null) {
- info_add_row(1, "Distance from pad", "%6.0f m", state.from_pad.distance);
- info_add_row(1, "Direction from pad", "%6.0f°", state.from_pad.bearing);
+ info_add_row(1, "Distance from pad", "%6d m",
+ (int) (state.from_pad.distance + 0.5));
+ info_add_row(1, "Direction from pad", "%6d°",
+ (int) (state.from_pad.bearing + 0.5));
+ info_add_row(1, "Elevation from pad", "%6d°",
+ (int) (state.elevation + 0.5));
+ info_add_row(1, "Range from pad", "%6d m",
+ (int) (state.range + 0.5));
} else {
info_add_row(1, "Distance from pad", "unknown");
info_add_row(1, "Direction from pad", "unknown");
+ info_add_row(1, "Elevation from pad", "unknown");
+ info_add_row(1, "Range from pad", "unknown");
}
info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S');
info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W');
class IdleThread extends Thread {
+ boolean started;
private AltosState state;
int reported_landing;
+ int report_interval;
+ long report_time;
- public void report(boolean last) {
+ public synchronized void report(boolean last) {
if (state == null)
return;
}
/* If the rocket isn't on the pad, then report height */
- if (state.state > Altos.ao_flight_pad) {
+ if (Altos.ao_flight_drogue <= state.state &&
+ state.state < Altos.ao_flight_landed &&
+ state.range >= 0)
+ {
+ voice.speak("Height %d, bearing %d, elevation %d, range %d.\n",
+ (int) (state.height + 0.5),
+ (int) (state.from_pad.bearing + 0.5),
+ (int) (state.elevation + 0.5),
+ (int) (state.range + 0.5));
+ } else if (state.state > Altos.ao_flight_pad) {
voice.speak("%d meters", (int) (state.height + 0.5));
} else {
reported_landing = 0;
* either we've got a landed report or we haven't heard from it in
* a long time
*/
- if (!state.ascent &&
+ if (state.state >= Altos.ao_flight_drogue &&
(last ||
System.currentTimeMillis() - state.report_time >= 15000 ||
state.state == Altos.ao_flight_landed))
else
voice.speak("rocket may have crashed");
if (state.from_pad != null)
- voice.speak("bearing %d degrees, range %d meters",
+ voice.speak("Bearing %d degrees, range %d meters.",
(int) (state.from_pad.bearing + 0.5),
(int) (state.from_pad.distance + 0.5));
++reported_landing;
}
}
+ long now () {
+ return System.currentTimeMillis();
+ }
+
+ void set_report_time() {
+ report_time = now() + report_interval;
+ }
+
public void run () {
reported_landing = 0;
state = null;
+ report_interval = 10000;
try {
for (;;) {
- Thread.sleep(10000);
+ set_report_time();
+ for (;;) {
+ voice.drain();
+ synchronized (this) {
+ long sleep_time = report_time - now();
+ if (sleep_time <= 0)
+ break;
+ wait(sleep_time);
+ }
+ }
report(false);
}
} catch (InterruptedException ie) {
+ try {
+ voice.drain();
+ } catch (InterruptedException iie) { }
}
}
- public void notice(AltosState new_state) {
+ public synchronized void notice(AltosState new_state, boolean spoken) {
+ AltosState old_state = state;
state = new_state;
+ if (!started && state.state > Altos.ao_flight_pad) {
+ started = true;
+ start();
+ }
+
+ if (state.state < Altos.ao_flight_drogue)
+ report_interval = 10000;
+ else
+ report_interval = 20000;
+ if (old_state != null && old_state.state != state.state) {
+ report_time = now();
+ this.notify();
+ } else if (spoken)
+ set_report_time();
}
}
- private void tell(AltosState state, AltosState old_state) {
+ private boolean tell(AltosState state, AltosState old_state) {
+ boolean ret = false;
if (old_state == null || old_state.state != state.state) {
voice.speak(state.data.state());
if ((old_state == null || old_state.state <= Altos.ao_flight_boost) &&
state.state > Altos.ao_flight_boost) {
voice.speak("max speed: %d meters per second.",
(int) (state.max_speed + 0.5));
+ ret = true;
} else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) &&
state.state >= Altos.ao_flight_drogue) {
voice.speak("max height: %d meters.",
(int) (state.max_height + 0.5));
+ ret = true;
}
}
if (old_state == null || old_state.gps_ready != state.gps_ready) {
- if (state.gps_ready)
+ if (state.gps_ready) {
voice.speak("GPS ready");
- else if (old_state != null)
+ ret = true;
+ }
+ else if (old_state != null) {
voice.speak("GPS lost");
+ ret = true;
+ }
}
old_state = state;
+ return ret;
}
class DisplayThread extends Thread {
String name;
- AltosRecord read() throws InterruptedException, ParseException { return null; }
+ int crc_errors;
+
+ void init() { }
- void close() { }
+ AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
+
+ void close(boolean interrupted) { }
void update(AltosState state) throws InterruptedException { }
public void run() {
+ boolean interrupted = false;
String line;
AltosState state = null;
AltosState old_state = null;
+ boolean told;
idle_thread = new IdleThread();
info_reset();
info_finish();
- idle_thread.start();
try {
for (;;) {
try {
old_state = state;
state = new AltosState(record, state);
update(state);
- show(state);
- tell(state, old_state);
- idle_thread.notice(state);
+ show(state, crc_errors);
+ told = tell(state, old_state);
+ idle_thread.notice(state, told);
} catch (ParseException pp) {
System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
+ } catch (AltosCRCException ce) {
+ ++crc_errors;
+ show(state, crc_errors);
}
}
} catch (InterruptedException ee) {
+ interrupted = true;
+ } catch (IOException ie) {
+ JOptionPane.showMessageDialog(AltosUI.this,
+ String.format("Error reading from \"%s\"", name),
+ "Telemetry Read Error",
+ JOptionPane.ERROR_MESSAGE);
} finally {
- close();
+ close(interrupted);
idle_thread.interrupt();
+ try {
+ idle_thread.join();
+ } catch (InterruptedException ie) {}
}
}
class DeviceThread extends DisplayThread {
AltosSerial serial;
- LinkedBlockingQueue<String> telem;
+ LinkedBlockingQueue<AltosLine> telem;
- AltosRecord read() throws InterruptedException, ParseException {
- return new AltosTelemetry(telem.take());
+ AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException {
+ AltosLine l = telem.take();
+ if (l.line == null)
+ throw new IOException("IO error");
+ return new AltosTelemetry(l.line);
}
- void close() {
+ void close(boolean interrupted) {
serial.close();
serial.remove_monitor(telem);
}
- public DeviceThread(AltosSerial s) {
+ public DeviceThread(AltosSerial s, String in_name) {
serial = s;
- telem = new LinkedBlockingQueue<String>();
+ telem = new LinkedBlockingQueue<AltosLine>();
serial.add_monitor(telem);
- name = "telemetry";
+ name = in_name;
}
}
if (device != null) {
try {
+ stop_display();
serial_line.open(device);
- DeviceThread thread = new DeviceThread(serial_line);
+ DeviceThread thread = new DeviceThread(serial_line, device.getPath());
serial_line.set_channel(AltosPreferences.channel());
serial_line.set_callsign(AltosPreferences.callsign());
run_display(thread);
void ConfigureTeleMetrum() {
new AltosConfig(AltosUI.this);
}
+
+ void FlashImage() {
+ new AltosFlashUI(AltosUI.this);
+ }
+
/*
* Open an existing telemetry file and replay it in realtime
*/
return null;
}
- public void close () {
- report();
+ public void close (boolean interrupted) {
+ if (!interrupted)
+ report();
}
public ReplayThread(AltosReader in_reader, String in_name) {
Thread display_thread;
private void stop_display() {
- if (display_thread != null && display_thread.isAlive())
+ if (display_thread != null && display_thread.isAlive()) {
display_thread.interrupt();
+ try {
+ display_thread.join();
+ } catch (InterruptedException ie) {}
+ }
display_thread = null;
}
* Replay a flight from telemetry data
*/
private void Replay() {
- JFileChooser logfile_chooser = new JFileChooser();
-
- logfile_chooser.setDialogTitle("Select Flight Record File");
- logfile_chooser.setFileFilter(new FileNameExtensionFilter("Flight data file", "eeprom", "telem"));
- logfile_chooser.setCurrentDirectory(AltosPreferences.logdir());
- int returnVal = logfile_chooser.showOpenDialog(AltosUI.this);
-
- if (returnVal == JFileChooser.APPROVE_OPTION) {
- File file = logfile_chooser.getSelectedFile();
- if (file == null)
- System.out.println("No file selected?");
- String filename = file.getName();
- try {
- FileInputStream replay = new FileInputStream(file);
- DisplayThread thread;
- if (filename.endsWith("eeprom"))
- thread = new ReplayEepromThread(replay, filename);
- else
- thread = new ReplayTelemetryThread(replay, filename);
- run_display(thread);
- } catch (FileNotFoundException ee) {
- JOptionPane.showMessageDialog(AltosUI.this,
- filename,
- "Cannot open telemetry file",
- JOptionPane.ERROR_MESSAGE);
- }
- }
+ AltosLogfileChooser chooser = new AltosLogfileChooser(
+ AltosUI.this);
+ AltosReader reader = chooser.runDialog();
+ if (reader != null)
+ run_display(new ReplayThread(reader,
+ chooser.filename()));
}
/* Connect to TeleMetrum, either directly or through
new AltosEepromDownload(AltosUI.this);
}
+ /* Load a flight log file and write out a CSV file containing
+ * all of the data in standard units
+ */
+
+ private void ExportData() {
+ new AltosCSVUI(AltosUI.this);
+ }
+
/* Create the AltosUI menus
*/
private void createMenu() {
});
menu.add(item);
+ item = new JMenuItem("Flash Image",KeyEvent.VK_F);
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ FlashImage();
+ }
+ });
+ menu.add(item);
+
+ item = new JMenuItem("Export Data",KeyEvent.VK_F);
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ ExportData();
+ }
+ });
+ menu.add(item);
+
item = new JMenuItem("Quit",KeyEvent.VK_Q);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
ActionEvent.CTRL_MASK));
this.setJMenuBar(menubar);
}
+
+ static String replace_extension(String input, String extension) {
+ int dot = input.lastIndexOf(".");
+ if (dot > 0)
+ input = input.substring(0,dot);
+ return input.concat(extension);
+ }
+
+ static AltosReader open_logfile(String filename) {
+ File file = new File (filename);
+ try {
+ FileInputStream in;
+
+ in = new FileInputStream(file);
+ if (filename.endsWith("eeprom"))
+ return new AltosEepromReader(in);
+ else
+ return new AltosTelemetryReader(in);
+ } catch (FileNotFoundException fe) {
+ System.out.printf("Cannot open '%s'\n", filename);
+ return null;
+ }
+ }
+
+ static AltosCSV open_csv(String filename) {
+ File file = new File (filename);
+ try {
+ return new AltosCSV(file);
+ } catch (FileNotFoundException fe) {
+ System.out.printf("Cannot open '%s'\n", filename);
+ return null;
+ }
+ }
+
+ static void process_file(String input) {
+ String output = replace_extension(input,".csv");
+ if (input.equals(output)) {
+ System.out.printf("Not processing '%s'\n", input);
+ return;
+ }
+ System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
+ AltosReader reader = open_logfile(input);
+ if (reader == null)
+ return;
+ AltosCSV writer = open_csv(output);
+ if (writer == null)
+ return;
+ writer.write(reader);
+ reader.close();
+ writer.close();
+ }
+
public static void main(final String[] args) {
- AltosUI altosui = new AltosUI();
- altosui.setVisible(true);
+
+ /* Handle batch-mode */
+ if (args.length > 0) {
+ for (int i = 0; i < args.length; i++)
+ process_file(args[i]);
+ } else {
+ AltosUI altosui = new AltosUI();
+ altosui.setVisible(true);
+ }
}
}
\ No newline at end of file
Voice voice;
LinkedBlockingQueue<String> phrases;
Thread thread;
+ boolean busy;
final static String voice_name = "kevin16";
for (;;) {
String s = phrases.take();
voice.speak(s);
+ synchronized(this) {
+ if (phrases.isEmpty()) {
+ busy = false;
+ notifyAll();
+ }
+ }
}
} catch (InterruptedException e) {
}
}
+ public synchronized void drain() throws InterruptedException {
+ while (busy)
+ wait();
+ }
+
public void speak_always(String s) {
try {
- if (voice != null)
- phrases.put(s);
+ if (voice != null) {
+ synchronized(this) {
+ busy = true;
+ phrases.put(s);
+ }
+ }
} catch (InterruptedException e) {
}
}
}
public AltosVoice () {
+ busy = false;
voice_manager = VoiceManager.getInstance();
voice = voice_manager.getVoice(voice_name);
if (voice != null) {
--- /dev/null
+#\r
+# InstDrv Example, (c) 2003 Jan Kiszka (Jan Kiszka@web.de)\r
+#\r
+\r
+Name "InstDrv.dll test"\r
+\r
+OutFile "InstDrv-Test.exe"\r
+\r
+ShowInstDetails show\r
+\r
+ComponentText "InstDrv Plugin Usage Example"\r
+\r
+Page components\r
+Page instfiles\r
+\r
+Section "Install a Driver" InstDriver\r
+ InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k"\r
+ Pop $0\r
+ DetailPrint "InitDriverSetup: $0"\r
+\r
+ InstDrv::DeleteOemInfFiles /NOUNLOAD\r
+ Pop $0\r
+ DetailPrint "DeleteOemInfFiles: $0"\r
+ StrCmp $0 "00000000" PrintInfNames ContInst1\r
+\r
+ PrintInfNames:\r
+ Pop $0\r
+ DetailPrint "Deleted $0"\r
+ Pop $0\r
+ DetailPrint "Deleted $0"\r
+\r
+ ContInst1:\r
+ InstDrv::CreateDevice /NOUNLOAD\r
+ Pop $0\r
+ DetailPrint "CreateDevice: $0"\r
+\r
+ SetOutPath $TEMP\r
+ File "ircomm2k.inf"\r
+ File "ircomm2k.sys"\r
+\r
+ InstDrv::InstallDriver /NOUNLOAD "$TEMP\ircomm2k.inf"\r
+ Pop $0\r
+ DetailPrint "InstallDriver: $0"\r
+ StrCmp $0 "00000000" PrintReboot ContInst2\r
+\r
+ PrintReboot:\r
+ Pop $0\r
+ DetailPrint "Reboot: $0"\r
+\r
+ ContInst2:\r
+ InstDrv::CountDevices\r
+ Pop $0\r
+ DetailPrint "CountDevices: $0"\r
+SectionEnd\r
+\r
+Section "Uninstall the driver again" UninstDriver\r
+ InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k"\r
+ Pop $0\r
+ DetailPrint "InitDriverSetup: $0"\r
+\r
+ InstDrv::DeleteOemInfFiles /NOUNLOAD\r
+ Pop $0\r
+ DetailPrint "DeleteOemInfFiles: $0"\r
+ StrCmp $0 "00000000" PrintInfNames ContUninst1\r
+\r
+ PrintInfNames:\r
+ Pop $0\r
+ DetailPrint "Deleted $0"\r
+ Pop $0\r
+ DetailPrint "Deleted $0"\r
+\r
+ ContUninst1:\r
+ InstDrv::RemoveAllDevices\r
+ Pop $0\r
+ DetailPrint "RemoveAllDevices: $0"\r
+ StrCmp $0 "00000000" PrintReboot ContUninst2\r
+\r
+ PrintReboot:\r
+ Pop $0\r
+ DetailPrint "Reboot: $0"\r
+\r
+ ContUninst2:\r
+ Delete "$SYSDIR\system32\ircomm2k.sys"\r
+SectionEnd
\ No newline at end of file
--- /dev/null
+/*\r
+\r
+InstDrv.dll - Installs or Removes Device Drivers\r
+\r
+Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de)\r
+\r
+This software is provided 'as-is', without any express or implied\r
+warranty. In no event will the authors be held liable for any damages\r
+arising from the use of this software.\r
+\r
+Permission is granted to anyone to use this software for any purpose,\r
+including commercial applications, and to alter it and redistribute\r
+it freely, subject to the following restrictions:\r
+\r
+1. The origin of this software must not be misrepresented; \r
+ you must not claim that you wrote the original software.\r
+ If you use this software in a product, an acknowledgment in the\r
+ product documentation would be appreciated but is not required.\r
+2. Altered versions must be plainly marked as such,\r
+ and must not be misrepresented as being the original software.\r
+3. This notice may not be removed or altered from any distribution.\r
+\r
+*/\r
+\r
+\r
+#include <windows.h>\r
+#include <setupapi.h>\r
+#include <newdev.h>\r
+#include "../exdll/exdll.h"\r
+\r
+\r
+char paramBuf[1024];\r
+GUID devClass;\r
+char hwIdBuf[1024];\r
+int initialized = 0;\r
+\r
+\r
+\r
+void* memset(void* dst, int val, unsigned int len)\r
+{\r
+ while (len-- > 0)\r
+ *((char *)dst)++ = val;\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+\r
+void* memcpy(void* dst, const void* src, unsigned int len)\r
+{\r
+ while (len-- > 0)\r
+ *((char *)dst)++ = *((char *)src)++;\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+\r
+int HexCharToInt(char c)\r
+{\r
+ if ((c >= '0') && (c <= '9'))\r
+ return c - '0';\r
+ else if ((c >= 'a') && (c <= 'f'))\r
+ return c - 'a' + 10;\r
+ else if ((c >= 'A') && (c <= 'F'))\r
+ return c - 'A' + 10;\r
+ else\r
+ return -1;\r
+}\r
+\r
+\r
+\r
+BOOLEAN HexStringToUInt(char* str, int width, void* valBuf)\r
+{\r
+ int i, val;\r
+\r
+\r
+ for (i = width - 4; i >= 0; i -= 4)\r
+ {\r
+ val = HexCharToInt(*str++);\r
+ if (val < 0)\r
+ return FALSE;\r
+ *(unsigned int *)valBuf += val << i;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+\r
+BOOLEAN StringToGUID(char* guidStr, GUID* pGuid)\r
+{\r
+ int i;\r
+\r
+\r
+ memset(pGuid, 0, sizeof(GUID));\r
+\r
+ if (*guidStr++ != '{')\r
+ return FALSE;\r
+\r
+ if (!HexStringToUInt(guidStr, 32, &pGuid->Data1))\r
+ return FALSE;\r
+ guidStr += 8;\r
+\r
+ if (*guidStr++ != '-')\r
+ return FALSE;\r
+\r
+ if (!HexStringToUInt(guidStr, 16, &pGuid->Data2))\r
+ return FALSE;\r
+ guidStr += 4;\r
+\r
+ if (*guidStr++ != '-')\r
+ return FALSE;\r
+\r
+ if (!HexStringToUInt(guidStr, 16, &pGuid->Data3))\r
+ return FALSE;\r
+ guidStr += 4;\r
+\r
+ if (*guidStr++ != '-')\r
+ return FALSE;\r
+\r
+ for (i = 0; i < 2; i++)\r
+ {\r
+ if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))\r
+ return FALSE;\r
+ guidStr += 2;\r
+ }\r
+\r
+ if (*guidStr++ != '-')\r
+ return FALSE;\r
+\r
+ for (i = 2; i < 8; i++)\r
+ {\r
+ if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))\r
+ return FALSE;\r
+ guidStr += 2;\r
+ }\r
+\r
+ if (*guidStr++ != '}')\r
+ return FALSE;\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+\r
+DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex)\r
+{\r
+ DWORD buffersize = 0;\r
+ LPTSTR buffer = NULL;\r
+ DWORD dataType;\r
+ DWORD result;\r
+\r
+\r
+ while (1)\r
+ {\r
+ if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData))\r
+ {\r
+ result = GetLastError();\r
+ break;\r
+ }\r
+\r
+ GetDeviceRegistryProperty:\r
+ if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID,\r
+ &dataType, (PBYTE)buffer, buffersize,\r
+ &buffersize))\r
+ {\r
+ result = GetLastError();\r
+\r
+ if (result == ERROR_INSUFFICIENT_BUFFER)\r
+ {\r
+ if (buffer != NULL)\r
+ LocalFree(buffer);\r
+\r
+ buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);\r
+\r
+ if (buffer == NULL)\r
+ break;\r
+\r
+ goto GetDeviceRegistryProperty;\r
+ }\r
+ else if (result == ERROR_INVALID_DATA)\r
+ continue; // ignore invalid entries\r
+ else\r
+ break; // break on other errors\r
+ }\r
+\r
+ if (lstrcmpi(buffer, hwIdBuf) == 0)\r
+ {\r
+ result = 0;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (buffer != NULL)\r
+ LocalFree(buffer);\r
+\r
+ return result;\r
+}\r
+\r
+\r
+\r
+DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId,\r
+ HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData,\r
+ DWORD *pIndex, DWORD flags)\r
+{\r
+ DWORD result;\r
+\r
+\r
+ *pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags);\r
+ if (*pDevInfoSet == INVALID_HANDLE_VALUE)\r
+ return GetLastError();\r
+\r
+ pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);\r
+ *pIndex = 0;\r
+\r
+ result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex);\r
+\r
+ if (result != 0)\r
+ SetupDiDestroyDeviceInfoList(*pDevInfoSet);\r
+\r
+ return result;\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::InitDriverSetup devClass drvHWID\r
+ *\r
+ * devClass - GUID of the driver's device setup class\r
+ * drvHWID - Hardware ID of the supported device\r
+ *\r
+ * Return:\r
+ * result - error message, empty on success\r
+ */\r
+void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+ EXDLL_INIT();\r
+\r
+ /* convert class GUID */\r
+ popstring(paramBuf);\r
+\r
+ if (!StringToGUID(paramBuf, &devClass))\r
+ {\r
+ popstring(paramBuf);\r
+ pushstring("Invalid GUID!");\r
+ return;\r
+ }\r
+\r
+ /* get hardware ID */\r
+ memset(hwIdBuf, 0, sizeof(hwIdBuf));\r
+ popstring(hwIdBuf);\r
+\r
+ initialized = 1;\r
+ pushstring("");\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::CountDevices\r
+ *\r
+ * Return:\r
+ * result - Number of installed devices the driver supports\r
+ */\r
+void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+ HDEVINFO devInfoSet;\r
+ SP_DEVINFO_DATA devInfoData;\r
+ int count = 0;\r
+ char countBuf[16];\r
+ DWORD index;\r
+ DWORD result;\r
+\r
+\r
+ EXDLL_INIT();\r
+\r
+ if (!initialized)\r
+ {\r
+ pushstring("Fatal error!");\r
+ return;\r
+ }\r
+\r
+ result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData,\r
+ &index, DIGCF_PRESENT);\r
+ if (result != 0)\r
+ {\r
+ pushstring("0");\r
+ return;\r
+ }\r
+\r
+ do\r
+ {\r
+ count++;\r
+ } while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0);\r
+\r
+ SetupDiDestroyDeviceInfoList(devInfoSet);\r
+\r
+ wsprintf(countBuf, "%d", count);\r
+ pushstring(countBuf);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::CreateDevice\r
+ *\r
+ * Return:\r
+ * result - Windows error code\r
+ */\r
+void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+ HDEVINFO devInfoSet;\r
+ SP_DEVINFO_DATA devInfoData;\r
+ DWORD result = 0;\r
+ char resultBuf[16];\r
+\r
+\r
+ EXDLL_INIT();\r
+\r
+ if (!initialized)\r
+ {\r
+ pushstring("Fatal error!");\r
+ return;\r
+ }\r
+\r
+ devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent);\r
+ if (devInfoSet == INVALID_HANDLE_VALUE)\r
+ {\r
+ wsprintf(resultBuf, "%08X", GetLastError());\r
+ pushstring(resultBuf);\r
+ return;\r
+ }\r
+\r
+ devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);\r
+ if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL,\r
+ hwndParent, DICD_GENERATE_ID, &devInfoData))\r
+ {\r
+ result = GetLastError();\r
+ goto InstallCleanup;\r
+ }\r
+\r
+ if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID,\r
+ hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR))) \r
+ {\r
+ result = GetLastError();\r
+ goto InstallCleanup;\r
+ }\r
+\r
+ if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData))\r
+ result = GetLastError();\r
+\r
+ InstallCleanup:\r
+ SetupDiDestroyDeviceInfoList(devInfoSet);\r
+\r
+ wsprintf(resultBuf, "%08X", result);\r
+ pushstring(resultBuf);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::InstallDriver infPath\r
+ *\r
+ * Return:\r
+ * result - Windows error code\r
+ * reboot - non-zero if reboot is required\r
+ */\r
+void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+ char resultBuf[16];\r
+ BOOL reboot;\r
+\r
+\r
+ EXDLL_INIT();\r
+ popstring(paramBuf);\r
+\r
+ if (!initialized)\r
+ {\r
+ pushstring("Fatal error!");\r
+ return;\r
+ }\r
+\r
+ if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf,\r
+ INSTALLFLAG_FORCE, &reboot))\r
+ {\r
+ wsprintf(resultBuf, "%08X", GetLastError());\r
+ pushstring(resultBuf);\r
+ }\r
+ else\r
+ {\r
+ wsprintf(resultBuf, "%d", reboot);\r
+ pushstring(resultBuf);\r
+ pushstring("00000000");\r
+ }\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::DeleteOemInfFiles\r
+ *\r
+ * Return:\r
+ * result - Windows error code\r
+ * oeminf - Path of the deleted devices setup file (oemXX.inf)\r
+ * oempnf - Path of the deleted devices setup file (oemXX.pnf)\r
+ */\r
+void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+ HDEVINFO devInfo;\r
+ SP_DEVINFO_DATA devInfoData;\r
+ SP_DRVINFO_DATA drvInfoData;\r
+ SP_DRVINFO_DETAIL_DATA drvInfoDetail;\r
+ DWORD index;\r
+ DWORD result;\r
+ char resultBuf[16];\r
+\r
+\r
+ if (!initialized)\r
+ {\r
+ pushstring("Fatal error!");\r
+ return;\r
+ }\r
+\r
+ result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);\r
+ if (result != 0)\r
+ goto Cleanup1;\r
+\r
+ if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER))\r
+ {\r
+ result = GetLastError();\r
+ goto Cleanup2;\r
+ }\r
+\r
+ drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);\r
+ drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);\r
+\r
+ if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData))\r
+ {\r
+ result = GetLastError();\r
+ goto Cleanup3;\r
+ }\r
+\r
+ if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData,\r
+ &drvInfoDetail, sizeof(drvInfoDetail), NULL))\r
+ {\r
+ result = GetLastError();\r
+\r
+ if (result != ERROR_INSUFFICIENT_BUFFER)\r
+ goto Cleanup3;\r
+\r
+ result = 0;\r
+ }\r
+\r
+ pushstring(drvInfoDetail.InfFileName);\r
+ if (!DeleteFile(drvInfoDetail.InfFileName))\r
+ result = GetLastError();\r
+ else\r
+ {\r
+ index = lstrlen(drvInfoDetail.InfFileName);\r
+ if (index > 3)\r
+ {\r
+ lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf");\r
+ pushstring(drvInfoDetail.InfFileName);\r
+ if (!DeleteFile(drvInfoDetail.InfFileName))\r
+ result = GetLastError();\r
+ }\r
+ }\r
+\r
+ Cleanup3:\r
+ SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER);\r
+\r
+ Cleanup2:\r
+ SetupDiDestroyDeviceInfoList(devInfo);\r
+\r
+ Cleanup1:\r
+ wsprintf(resultBuf, "%08X", result);\r
+ pushstring(resultBuf);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::RemoveAllDevices\r
+ *\r
+ * Return:\r
+ * result - Windows error code\r
+ * reboot - non-zero if reboot is required\r
+ */\r
+void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+ HDEVINFO devInfo;\r
+ SP_DEVINFO_DATA devInfoData;\r
+ DWORD index;\r
+ DWORD result;\r
+ char resultBuf[16];\r
+ BOOL reboot = FALSE;\r
+ SP_DEVINSTALL_PARAMS instParams;\r
+\r
+\r
+ EXDLL_INIT();\r
+\r
+ if (!initialized)\r
+ {\r
+ pushstring("Fatal error!");\r
+ return;\r
+ }\r
+\r
+ result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);\r
+ if (result != 0)\r
+ goto Cleanup1;\r
+\r
+ do\r
+ {\r
+ if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData))\r
+ {\r
+ result = GetLastError();\r
+ break;\r
+ }\r
+\r
+ instParams.cbSize = sizeof(instParams);\r
+ if (!reboot &&\r
+ SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) &&\r
+ ((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0))\r
+ {\r
+ reboot = TRUE;\r
+ }\r
+\r
+ result = FindNextDevice(devInfo, &devInfoData, &index);\r
+ } while (result == 0);\r
+\r
+ SetupDiDestroyDeviceInfoList(devInfo);\r
+\r
+ Cleanup1:\r
+ if ((result == 0) || (result == ERROR_NO_MORE_ITEMS))\r
+ {\r
+ wsprintf(resultBuf, "%d", reboot);\r
+ pushstring(resultBuf);\r
+ pushstring("00000000");\r
+ }\r
+ else\r
+ {\r
+ wsprintf(resultBuf, "%08X", result);\r
+ pushstring(resultBuf);\r
+ }\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::StartSystemService serviceName\r
+ *\r
+ * Return:\r
+ * result - Windows error code\r
+ */\r
+void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+ SC_HANDLE managerHndl;\r
+ SC_HANDLE svcHndl;\r
+ SERVICE_STATUS svcStatus;\r
+ DWORD oldCheckPoint;\r
+ DWORD result;\r
+ char resultBuf[16];\r
+\r
+\r
+ EXDLL_INIT();\r
+ popstring(paramBuf);\r
+\r
+ managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);\r
+ if (managerHndl == NULL)\r
+ {\r
+ result = GetLastError();\r
+ goto Cleanup1;\r
+ }\r
+\r
+ svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS);\r
+ if (svcHndl == NULL)\r
+ {\r
+ result = GetLastError();\r
+ goto Cleanup2;\r
+ }\r
+\r
+ if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus))\r
+ {\r
+ result = GetLastError();\r
+ goto Cleanup3;\r
+ }\r
+\r
+ while (svcStatus.dwCurrentState == SERVICE_START_PENDING)\r
+ {\r
+ oldCheckPoint = svcStatus.dwCheckPoint;\r
+\r
+ Sleep(svcStatus.dwWaitHint);\r
+\r
+ if (!QueryServiceStatus(svcHndl, &svcStatus))\r
+ {\r
+ result = GetLastError();\r
+ break;\r
+ }\r
+\r
+ if (oldCheckPoint >= svcStatus.dwCheckPoint)\r
+ {\r
+ if ((svcStatus.dwCurrentState == SERVICE_STOPPED) &&\r
+ (svcStatus.dwWin32ExitCode != 0))\r
+ result = svcStatus.dwWin32ExitCode;\r
+ else\r
+ result = ERROR_SERVICE_REQUEST_TIMEOUT;\r
+ }\r
+ }\r
+\r
+ if (svcStatus.dwCurrentState == SERVICE_RUNNING)\r
+ result = 0;\r
+\r
+ Cleanup3:\r
+ CloseServiceHandle(svcHndl);\r
+\r
+ Cleanup2:\r
+ CloseServiceHandle(managerHndl);\r
+\r
+ Cleanup1:\r
+ wsprintf(resultBuf, "%08X", result);\r
+ pushstring(resultBuf);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::StopSystemService serviceName\r
+ *\r
+ * Return:\r
+ * result - Windows error code\r
+ */\r
+void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+ SC_HANDLE managerHndl;\r
+ SC_HANDLE svcHndl;\r
+ SERVICE_STATUS svcStatus;\r
+ DWORD oldCheckPoint;\r
+ DWORD result;\r
+ char resultBuf[16];\r
+\r
+\r
+ EXDLL_INIT();\r
+ popstring(paramBuf);\r
+\r
+ managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);\r
+ if (managerHndl == NULL)\r
+ {\r
+ result = GetLastError();\r
+ goto Cleanup1;\r
+ }\r
+\r
+ svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS);\r
+ if (svcHndl == NULL)\r
+ {\r
+ result = GetLastError();\r
+ goto Cleanup2;\r
+ }\r
+\r
+ if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus))\r
+ {\r
+ result = GetLastError();\r
+ goto Cleanup3;\r
+ }\r
+\r
+ while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING)\r
+ {\r
+ oldCheckPoint = svcStatus.dwCheckPoint;\r
+\r
+ Sleep(svcStatus.dwWaitHint);\r
+\r
+ if (!QueryServiceStatus(svcHndl, &svcStatus))\r
+ {\r
+ result = GetLastError();\r
+ break;\r
+ }\r
+\r
+ if (oldCheckPoint >= svcStatus.dwCheckPoint)\r
+ {\r
+ result = ERROR_SERVICE_REQUEST_TIMEOUT;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (svcStatus.dwCurrentState == SERVICE_STOPPED)\r
+ result = 0;\r
+\r
+ Cleanup3:\r
+ CloseServiceHandle(svcHndl);\r
+\r
+ Cleanup2:\r
+ CloseServiceHandle(managerHndl);\r
+\r
+ Cleanup1:\r
+ wsprintf(resultBuf, "%08X", result);\r
+ pushstring(resultBuf);\r
+}\r
+\r
+\r
+\r
+BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)\r
+{\r
+ return TRUE;\r
+}\r
--- /dev/null
+# Microsoft Developer Studio Project File - Name="InstDrv" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** NICHT BEARBEITEN **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=InstDrv - Win32 Debug\r
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE\r
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "InstDrv.mak".\r
+!MESSAGE \r
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben\r
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "InstDrv.mak" CFG="InstDrv - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Für die Konfiguration stehen zur Auswahl:\r
+!MESSAGE \r
+!MESSAGE "InstDrv - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "InstDrv - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF "$(CFG)" == "InstDrv - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /c\r
+# ADD CPP /nologo /MT /W3 /GX /O1 /I "C:\Programme\WINDDK\3790\inc\ddk\w2k" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /FD /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x407 /d "NDEBUG"\r
+# ADD RSC /l 0x407 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib setupapi.lib newdev.lib /nologo /entry:"_DllMainCRTStartup" /dll /machine:I386 /nodefaultlib /out:"../../Plugins/InstDrv.dll" /libpath:"C:\Programme\WINDDK\3790\lib\w2k\i386" /opt:nowin98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF "$(CFG)" == "InstDrv - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /GZ /c\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x407 /d "_DEBUG"\r
+# ADD RSC /l 0x407 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"_DllMainCRTStartup" /dll /debug /machine:I386 /pdbtype:sept\r
+# SUBTRACT LINK32 /nodefaultlib\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "InstDrv - Win32 Release"\r
+# Name "InstDrv - Win32 Debug"\r
+# Begin Group "Quellcodedateien"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\InstDrv.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header-Dateien"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# End Group\r
+# Begin Group "Ressourcendateien"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
--- /dev/null
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!\r
+\r
+###############################################################################\r
+\r
+Project: "InstDrv"=.\InstDrv.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
--- /dev/null
+InstDrv.dll version 0.2 - Installs or Removes Device Drivers\r
+------------------------------------------------------------\r
+\r
+\r
+The plugin helps you to create NSIS scripts for installing device drivers or\r
+removing them again. It can count installed device instances, create new ones\r
+or delete all supported device. InstDrv works on Windows 2000 or later.\r
+\r
+\r
+\r
+InstDrv::InitDriverSetup devClass drvHWID\r
+Return: result\r
+\r
+To start processing a driver, first call this function. devClass is the GUID\r
+of the device class the driver supports, drvHWID is the device hardware ID. If\r
+you don't know what these terms mean, you may want to take a look at the\r
+Windows DDK. This function returns an empty string on success, otherwise an\r
+error message.\r
+\r
+InitDriverSetup has to be called every time after the plugin dll has been\r
+(re-)loaded, or if you want to switch to a different driver.\r
+\r
+\r
+\r
+InstDrv::CountDevices\r
+Return: number\r
+\r
+This call returns the number of installed and supported devices of the driver.\r
+\r
+\r
+\r
+InstDrv::CreateDevice\r
+Return: result\r
+\r
+To create a new deviced node which the driver has to support, use this\r
+function. You may even call it multiple times for more than one instance. The\r
+return value is the Windows error code (in hex). Use CreateDevice before\r
+installing or updating the driver itself.\r
+\r
+\r
+\r
+InstDrv::InstallDriver infPath\r
+Return: result\r
+ reboot\r
+\r
+InstallDriver installs or updates a device driver as specified in the .inf\r
+setup script. It returns a Windows error code (in hex) and, on success, a flag\r
+signalling if a system reboot is required.\r
+\r
+\r
+\r
+InstDrv::DeleteOemInfFiles\r
+Return: result\r
+ oeminf\r
+ oempnf\r
+\r
+DeleteOemInfFiles tries to clean up the Windows inf directory by deleting the\r
+oemXX.inf and oemXX.pnf files associated with the drivers. It returns a\r
+Windows error code (in hex) and, on success, the names of the deleted files.\r
+This functions requires that at least one device instance is still present.\r
+So, call it before you remove the devices itself. You should also call it\r
+before updating a driver. This avoids that the inf directory gets slowly\r
+messed up with useless old setup scripts (which does NOT really accelerate\r
+Windows). The error code which comes up when no device is installed is\r
+"00000103".\r
+\r
+\r
+\r
+InstDrv::RemoveAllDevices\r
+Return: result\r
+ reboot\r
+\r
+This functions deletes all devices instances the driver supported. It returns\r
+a Windows error code (in hex) and, on success, a flag signalling if the system\r
+needs to be rebooted. You additionally have to remove the driver binaries from\r
+the system paths.\r
+\r
+\r
+\r
+InstDrv::StartSystemService serviceName\r
+Return: result\r
+\r
+Call this function to start the provided system service. The function blocks\r
+until the service is started or the system reported a timeout. The return value\r
+is the Windows error code (in hex).\r
+\r
+\r
+\r
+InstDrv::StopSystemService serviceName\r
+Return: result\r
+\r
+This function tries to stop the provided system service. It blocks until the\r
+service has been shut down or the system reported a timeout. The return value\r
+is the Windows error code (in hex).\r
+\r
+\r
+\r
+Example.nsi\r
+\r
+The example script installs or removes the virtual COM port driver of IrCOMM2k\r
+(2.0.0-alpha8, see www.ircomm2k.de/english). The driver and its setup script\r
+are only included for demonstration purposes, they do not work without the\r
+rest of IrCOMM2k (but they also do not cause any harm).\r
+\r
+\r
+\r
+Building the Source Code\r
+\r
+To build the plugin from the source code, some include files and libraries\r
+which come with the Windows DDK are required.\r
+\r
+\r
+\r
+History\r
+\r
+ 0.2 - fixed bug when calling InitDriverSetup the second time\r
+ - added StartSystemService and StopSystemService\r
+\r
+ 0.1 - first release\r
+\r
+\r
+\r
+License\r
+\r
+Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de)\r
+\r
+This software is provided 'as-is', without any express or implied\r
+warranty. In no event will the authors be held liable for any damages\r
+arising from the use of this software.\r
+\r
+Permission is granted to anyone to use this software for any purpose,\r
+including commercial applications, and to alter it and redistribute\r
+it freely, subject to the following restrictions:\r
+\r
+1. The origin of this software must not be misrepresented; \r
+ you must not claim that you wrote the original software.\r
+ If you use this software in a product, an acknowledgment in the\r
+ product documentation would be appreciated but is not required.\r
+2. Altered versions must be plainly marked as such,\r
+ and must not be misrepresented as being the original software.\r
+3. This notice may not be removed or altered from any distribution.\r
--- /dev/null
+; IrCOMM2k.inf\r
+;\r
+; Installation file for the Virtual Infrared-COM-Port\r
+;\r
+; (c) Copyright 2001, 2002 Jan Kiszka \r
+;\r
+\r
+[Version]\r
+Signature="$Windows NT$"\r
+Provider=%JK%\r
+Class=Ports\r
+ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318}\r
+;DriverVer=03/26/2002,1.2.1.0\r
+\r
+[DestinationDirs]\r
+IrCOMM2k.Copy2Drivers = 12\r
+IrCOMM2k.Copy2Winnt = 10\r
+IrCOMM2k.Copy2System32 = 11\r
+IrCOMM2k.Copy2Help = 18\r
+\r
+\r
+;\r
+; Driver information\r
+;\r
+\r
+[Manufacturer]\r
+%JK% = JK.Mfg\r
+\r
+[JK.Mfg]\r
+%JK.DeviceDescIrCOMM% = IrCOMM2k_inst,IrCOMM2k\r
+\r
+\r
+;\r
+; General installation section\r
+;\r
+\r
+[IrCOMM2k_inst]\r
+CopyFiles = IrCOMM2k.Copy2Drivers ;,IrCOMM2k.Copy2System32,IrCOMM2k.Copy2Help,IrCOMM2k.Copy2Winnt\r
+;AddReg = IrCOMM2k_inst_AddReg\r
+\r
+\r
+;\r
+; File sections\r
+;\r
+\r
+[IrCOMM2k.Copy2Drivers]\r
+ircomm2k.sys,,,2\r
+\r
+;[IrCOMM2k.Copy2System32]\r
+;ircomm2k.exe,,,2\r
+;ircomm2k.dll,,,2\r
+\r
+;[IrCOMM2k.Copy2Help]\r
+;ircomm2k.hlp,,,2\r
+\r
+;[IrCOMM2k.Copy2Winnt]\r
+;IrCOMM2k-Setup.exe,Setup.exe,,2\r
+\r
+\r
+;\r
+; Service Installation\r
+;\r
+\r
+[IrCOMM2k_inst.Services]\r
+AddService = IrCOMM2k,0x00000002,IrCOMM2k_DriverService_Inst,IrCOMM2k_DriverEventLog_Inst\r
+;AddService = IrCOMM2kSvc,,IrCOMM2k_Service_Inst\r
+\r
+[IrCOMM2k_DriverService_Inst]\r
+DisplayName = %IrCOMM2k.DrvName%\r
+ServiceType = 1 ; SERVICE_KERNEL_DRIVER\r
+StartType = 3 ; SERVICE_DEMAND_START\r
+ErrorControl = 0 ; SERVICE_ERROR_IGNORE\r
+ServiceBinary = %12%\ircomm2k.sys\r
+\r
+;[IrCOMM2k_Service_Inst]\r
+;DisplayName = %IrCOMM2k.SvcName%\r
+;Description = %IrCOMM2k.SvcDesc%\r
+;ServiceType = 0x00000120 ; SERVICE_WIN32_SHARE_PROCESS, SERVICE_INTERACTIVE_PROCESS\r
+;StartType = 2 ; SERVICE_AUTO_START\r
+;ErrorControl = 0 ; SERVICE_ERROR_IGNORE\r
+;ServiceBinary = %11%\ircomm2k.exe\r
+;Dependencies = IrCOMM2k\r
+;AddReg = IrCOMM2kSvcAddReg\r
+\r
+\r
+[IrCOMM2k_inst.nt.HW]\r
+AddReg=IrCOMM2kHwAddReg\r
+\r
+[IrCOMM2kHwAddReg]\r
+HKR,,PortSubClass,REG_BINARY,0x00000001\r
+;HKR,,TimeoutScaling,REG_DWORD,0x00000001\r
+;HKR,,StatusLines,REG_DWORD,0x00000000\r
+\r
+;[IrCOMM2k_inst_AddReg]\r
+;HKR,,EnumPropPages32,,"ircomm2k.dll,IrCOMM2kPropPageProvider"\r
+;HKLM,%UNINSTALL_KEY%,DisplayIcon,0x00020000,"%windir%\IrCOMM2k-Setup.exe"\r
+;HKLM,%UNINSTALL_KEY%,DisplayName,,"IrCOMM2k 1.2.1 "\r
+;HKLM,%UNINSTALL_KEY%,DisplayVersion,,"1.2.1"\r
+;HKLM,%UNINSTALL_KEY%,HelpLink,,"http://www.ircomm2k.de"\r
+;HKLM,%UNINSTALL_KEY%,Publisher,,%JK%\r
+;HKLM,%UNINSTALL_KEY%,UninstallString,0x00020000,"%windir%\IrCOMM2k-Setup.exe"\r
+\r
+;[IrCOMM2kSvcAddReg]\r
+;HKR,Parameters,ActiveConnectOnly,REG_DWORD,0x00000000\r
+\r
+\r
+[IrCOMM2k_DriverEventLog_Inst]\r
+AddReg = IrCOMM2k_DriverEventLog_AddReg\r
+\r
+[IrCOMM2k_DriverEventLog_AddReg]\r
+HKR,,EventMessageFile,REG_EXPAND_SZ,"%SystemRoot%\System32\IoLogMsg.dll;%SystemRoot%\System32\drivers\ircomm2k.sys"\r
+HKR,,TypesSupported,REG_DWORD,7\r
+\r
+\r
+[Strings]\r
+\r
+;\r
+; Non-Localizable Strings\r
+;\r
+\r
+REG_SZ = 0x00000000\r
+REG_MULTI_SZ = 0x00010000\r
+REG_EXPAND_SZ = 0x00020000\r
+REG_BINARY = 0x00000001\r
+REG_DWORD = 0x00010001\r
+SERVICEROOT = "System\CurrentControlSet\Services"\r
+UNINSTALL_KEY = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IrCOMM2k"\r
+\r
+;\r
+; Localizable Strings\r
+;\r
+\r
+JK = "Jan Kiszka"\r
+JK.DeviceDescIrCOMM = "Virtueller Infrarot-Kommunikationsanschluss"\r
+IrCOMM2k.DrvName = "Virtueller Infrarot-Kommunikationsanschluss"\r
+;IrCOMM2k.SvcName = "Virtueller Infrarot-Kommunikationsanschluß, Dienstprogramm"\r
+;IrCOMM2k.SvcDesc = "Bildet über Infarot einen Kommunikationsanschluß nach."\r
+++ /dev/null
-.SUFFIXES: .java .class
-
-CLASSPATH=classes:./*:/usr/share/java/*
-CLASSFILES=\
- Altos.class \
- AltosChannelMenu.class \
- AltosConfig.class \
- AltosConfigUI.class \
- AltosConvert.class \
- AltosCSV.class \
- AltosEepromDownload.class \
- AltosEepromMonitor.class \
- AltosEepromReader.class \
- AltosEepromRecord.class \
- AltosFile.class \
- AltosFlightInfoTableModel.class \
- AltosFlightStatusTableModel.class \
- AltosGPS.class \
- AltosGreatCircle.class \
- AltosLog.class \
- AltosParse.class \
- AltosPreferences.class \
- AltosRecord.class \
- AltosSerialMonitor.class \
- AltosSerial.class \
- AltosState.class \
- AltosTelemetry.class \
- AltosTelemetryReader.class \
- AltosUI.class \
- AltosDevice.class \
- AltosDeviceDialog.class \
- AltosVoice.class
-
-#FREETTSSRC=/home/keithp/src/freetts/freetts-1.2.2
-#FREETTSLIB=$(FREETTSSRC)/lib
-#FREETTSJAR=/usr/share/java/freetts.jar
-#FREETTSJAR= \
-# cmudict04.jar \
-# cmulex.jar \
-# cmu_time_awb.jar \
-# cmutimelex.jar \
-# cmu_us_kal.jar \
-# en_us.jar \
-# freetts.jar
-
-JAVAFLAGS=-Xlint:unchecked -Xlint:deprecation
-
-OS:=$(shell uname)
-
-ifeq ($(OS),Linux)
-ALTOSUI_APP=altosui
-endif
-
-ifeq ($(OS),Darwin)
-ALTOSUI_APP=AltosUI.app/Contents/Resources/Java/altosui.jar
-endif
-
-all: altosui.jar $(ALTOSUI_APP)
-
-$(CLASSFILES):
-
-.java.class:
- javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
-
-altosui.jar: classes/altosui classes/libaltosJNI $(FREETTSJAR) $(CLASSFILES) Manifest.txt
- cd ./classes && jar cfm ../$@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class
-
-classes/altosui:
- mkdir -p classes
- ln -sf .. classes/altosui
-
-classes/libaltosJNI:
- mkdir -p classes
- ln -sf ../../libaltos/libaltosJNI classes/libaltosJNI
-
-#$(FREETTSJAR):
-# ln -s $(FREETTSLIB)/$@ .
-
-ifeq ($(OS),Darwin)
-RESOURCES=altosui.jar $(FREETTSJAR) ../libaltos/libaltos.dylib
-
-$(ALTOSUI_APP): $(RESOURCES)
- mkdir -p AltosUI.app/Contents/Resources/Java
- cp $(RESOURCES) AltosUI.app/Contents/Resources/Java
-
-endif
-
-ifeq ($(OS),Linux)
-altosui:
- echo "#!/bin/sh" > $@
- echo "exec java -Djava.library.path=../libaltos -jar altosui.jar" >> $@
- chmod +x ./altosui
-endif
-
-clean:
- rm -f *.class altosui.jar
- rm -f AltosUI.app/Contents/Resources/Java/*
- rm -rf classes
--- /dev/null
+.SUFFIXES: .java .class
+
+CLASSPATH=classes:./*:/usr/share/java/*
+CLASSFILES=\
+ Altos.class \
+ AltosChannelMenu.class \
+ AltosConfig.class \
+ AltosConfigUI.class \
+ AltosConvert.class \
+ AltosCRCException.class \
+ AltosCSV.class \
+ AltosCSVUI.class \
+ AltosDebug.class \
+ AltosEepromDownload.class \
+ AltosEepromMonitor.class \
+ AltosEepromReader.class \
+ AltosEepromRecord.class \
+ AltosFile.class \
+ AltosFlash.class \
+ AltosFlashUI.class \
+ AltosFlightInfoTableModel.class \
+ AltosFlightStatusTableModel.class \
+ AltosGPS.class \
+ AltosGreatCircle.class \
+ AltosHexfile.class \
+ AltosLine.class \
+ AltosLog.class \
+ AltosLogfileChooser.class \
+ AltosParse.class \
+ AltosPreferences.class \
+ AltosReader.class \
+ AltosRecord.class \
+ AltosSerialMonitor.class \
+ AltosSerial.class \
+ AltosState.class \
+ AltosTelemetry.class \
+ AltosTelemetryReader.class \
+ AltosUI.class \
+ AltosDevice.class \
+ AltosDeviceDialog.class \
+ AltosRomconfig.class \
+ AltosRomconfigUI.class \
+ AltosVoice.class
+
+JAVA_ICON=../../icon/altus-metrum-16x16.jpg
+WINDOWS_ICON=../../icon/altus-metrum.ico
+
+# where altosui.jar gets installed
+ALTOSLIB=/usr/share/java
+
+# where freetts.jar is to be found
+FREETTSLIB=/usr/share/java
+
+# all of the freetts files
+FREETTSJAR= \
+ $(FREETTSLIB)/cmudict04.jar \
+ $(FREETTSLIB)/cmulex.jar \
+ $(FREETTSLIB)/cmu_time_awb.jar \
+ $(FREETTSLIB)/cmutimelex.jar \
+ $(FREETTSLIB)/cmu_us_kal.jar \
+ $(FREETTSLIB)/en_us.jar \
+ $(FREETTSLIB)/freetts.jar
+
+# The current hex files
+HEXLIB=../../src
+HEXFILES = \
+ $(HEXLIB)/telemetrum-v1.0.ihx \
+ $(HEXLIB)/teledongle-v0.2.ihx
+
+JAVAFLAGS=-Xlint:unchecked -Xlint:deprecation
+
+ALTOSUIJAR = altosui.jar
+FATJAR = fat/altosui.jar
+
+OS:=$(shell uname)
+
+LINUX_APP=altosui
+
+DARWIN_ZIP=Altos-Mac.zip
+
+WINDOWS_EXE=Altos-Windows.exe
+
+LINUX_TGZ=Altos-Linux.tgz
+
+all: altosui.jar $(LINUX_APP)
+fat: altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ)
+
+$(CLASSFILES):
+
+.java.class:
+ javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
+
+altosui.jar: classes/images classes/altosui classes/libaltosJNI $(CLASSFILES) Manifest.txt
+ cd ./classes && jar cfm ../$@ altosui/Manifest.txt images/* altosui/*.class libaltosJNI/*.class
+
+Manifest.txt: Makefile $(CLASSFILES)
+ echo 'Main-Class: altosui.AltosUI' > $@
+ echo "Class-Path: $(FREETTSLIB)/freetts.jar" >> $@
+
+classes/altosui:
+ mkdir -p classes
+ ln -sf .. classes/altosui
+
+classes/libaltosJNI:
+ mkdir -p classes
+ ln -sf ../../libaltos/libaltosJNI classes/libaltosJNI
+
+classes/images:
+ mkdir -p classes/images
+ ln -sf ../../$(JAVA_ICON) classes/images
+
+altosui:
+ echo "#!/bin/sh" > $@
+ echo "exec java -Djava.library.path=/usr/lib/altos -jar /usr/share/java/altosui.jar" >> $@
+ chmod +x ./altosui
+
+fat/altosui:
+ echo "#!/bin/sh" > $@
+ echo 'ME=`which "$0"`' >> $@
+ echo 'DIR=`dirname "$ME"`' >> $@
+ echo 'exec java -Djava.library.path="$$DIR" -jar "$$DIR"/altosui.jar' >> $@
+ chmod +x $@
+
+fat/altosui.jar: $(CLASSFILES) $(JAVA_ICON) fat/classes/Manifest.txt
+ mkdir -p fat/classes
+ test -L fat/classes/altosui || ln -sf ../.. fat/classes/altosui
+ mkdir -p fat/classes/images
+ cp $(JAVA_ICON) fat/classes/images
+ test -L fat/classes/libaltosJNI || ln -sf ../../../libaltos/libaltosJNI fat/classes/libaltosJNI
+ cd ./fat/classes && jar cfm ../../$@ Manifest.txt images/* altosui/*.class libaltosJNI/*.class
+
+fat/classes/Manifest.txt: $(CLASSFILES) Makefile
+ mkdir -p fat/classes
+ echo 'Main-Class: altosui.AltosUI' > $@
+ echo "Class-Path: freetts.jar" >> $@
+
+install: altosui.jar altosui
+ install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar
+ install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/man1/altosui.1
+ install altosui $(DESTDIR)/usr/bin/altosui
+
+clean:
+ rm -f *.class altosui.jar
+ rm -f AltosUI.app/Contents/Resources/Java/*
+ rm -rf classes
+ rm -rf windows linux
+
+distclean: clean
+ rm -f $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ)
+ rm -rf darwin fat
+
+FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES)
+
+LINUX_FILES=$(FAT_FILES) ../libaltos/libaltos.so fat/altosui
+$(LINUX_TGZ): $(LINUX_FILES)
+ rm -f $@
+ mkdir -p linux/AltOS
+ rm -f linux/AltOS/*
+ cp $(LINUX_FILES) linux/AltOS
+ cd linux && tar czf ../$@ AltOS
+
+DARWIN_RESOURCES=$(FATJAR) $(FREETTSJAR) ../libaltos/libaltos.dylib
+DARWIN_EXTRA=$(HEXFILES)
+DARWIN_FILES=$(DARWIN_RESOURCES) $(DARWIN_EXTRA)
+
+$(DARWIN_ZIP): $(DARWIN_FILES)
+ rm -f $@
+ cp -a AltosUI.app darwin/
+ mkdir -p darwin/AltosUI.app/Contents/Resources/Java
+ cp $(DARWIN_RESOURCES) darwin/AltosUI.app/Contents/Resources/Java
+ mkdir -p darwin/AltOS
+ cp $(DARWIN_EXTRA) darwin/AltOS
+ cd darwin && zip -r ../$@ AltosUI.app AltOS
+
+WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf $(WINDOWS_ICON)
+
+$(WINDOWS_EXE): $(WINDOWS_FILES) altos-windows.nsi
+ rm -f $@
+ mkdir -p windows/AltOS
+ rm -f windows/AltOS/*
+ cp $(WINDOWS_FILES) windows/AltOS
+ makensis altos-windows.nsi
--- /dev/null
+JAVAROOT=classes
+AM_JAVACFLAGS=-encoding UTF-8
+
+CLASSPATH_ENV=CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*"
+
+bin_SCRIPTS=altosui
+
+altosui_JAVA = \
+ AltosChannelMenu.java \
+ AltosConfig.java \
+ AltosConfigUI.java \
+ AltosConvert.java \
+ AltosCRCException.java \
+ AltosCSV.java \
+ AltosCSVUI.java \
+ AltosDebug.java \
+ AltosDeviceDialog.java \
+ AltosDevice.java \
+ AltosEepromDownload.java \
+ AltosEepromMonitor.java \
+ AltosEepromReader.java \
+ AltosEepromRecord.java \
+ AltosFile.java \
+ AltosFlash.java \
+ AltosFlashUI.java \
+ AltosFlightInfoTableModel.java \
+ AltosFlightStatusTableModel.java \
+ AltosGPS.java \
+ AltosGreatCircle.java \
+ AltosHexfile.java \
+ Altos.java \
+ AltosLine.java \
+ AltosLogfileChooser.java \
+ AltosLog.java \
+ AltosParse.java \
+ AltosPreferences.java \
+ AltosReader.java \
+ AltosRecord.java \
+ AltosRomconfig.java \
+ AltosRomconfigUI.java \
+ AltosSerial.java \
+ AltosSerialMonitor.java \
+ AltosState.java \
+ AltosTelemetry.java \
+ AltosTelemetryReader.java \
+ AltosUI.java \
+ AltosVoice.java
+
+FREETTS_CLASS= \
+ cmudict04.jar \
+ cmulex.jar \
+ cmu_time_awb.jar \
+ cmutimelex.jar \
+ cmu_us_kal.jar \
+ en_us.jar \
+ freetts.jar
+
+LIBALTOS= \
+ libaltos.so \
+ libaltos.dylib \
+ altos.dll
+
+JAR=altosui.jar
+
+FATJAR=altosui-fat.jar
+
+# Icons
+JAVA_ICON=$(top_srcdir)/icon/altus-metrum-16x16.jpg
+WINDOWS_ICON=$(top_srcdir)/icon/altus-metrum.ico
+
+# Firmware
+FIRMWARE_TD=$(top_srcdir)/src/teledongle-v0.2-$(VERSION).ihx
+FIRMWARE_TM=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx
+FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TD)
+
+# Distribution targets
+LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2
+MACOSX_DIST=Altos-Mac-$(VERSION).zip
+WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe
+
+FAT_FILES=$(FATJAR) $(FREETTS_CLASS)
+
+LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE)
+LINUX_EXTRA=altosui-fat
+
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib
+MACOSX_EXTRA=$(FIRMWARE)
+
+WINDOWS_FILES=$(FAT_FILES) altos.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON)
+
+all-local: classes/altosui $(JAR) $(FATJAR) altosui altosui-test
+
+clean-local:
+ -rm -rf classes/altosui $(JAR) $(FATJAR) \
+ $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST) $(FREETTS_CLASS) \
+ $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \
+ altosui altosui-test macosx linux
+
+fat: $(FATJAR) $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST)
+
+altosuidir=$(datadir)/java
+
+install-altosuiJAVA: altosui.jar
+ @$(NORMAL_INSTALL)
+ test -z "$(altosuidir)" || $(MKDIR_P) "$(DESTDIR)$(altosuidir)"
+ echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosuidir)/altosui.jar'"; \
+ $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosuidir)"
+
+classes/altosui:
+ mkdir -p classes/altosui
+
+$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON)
+ jar cfm $@ Manifest.txt \
+ -C $(top_srcdir)/icon altus-metrum-16x16.jpg \
+ -C classes altosui \
+ -C ../libaltos libaltosJNI
+
+$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(LIBALTOS) $(JAVA_ICON)
+ jar cfm $@ Manifest-fat.txt \
+ -C $(top_srcdir)/icon altus-metrum-16x16.jpg \
+ -C classes altosui \
+ -C ../libaltos libaltosJNI
+
+Manifest.txt: Makefile
+ echo 'Main-Class: altosui.AltosUI' > $@
+ echo "Class-Path: $(FREETTS)/freetts.jar" >> $@
+
+Manifest-fat.txt:
+ echo 'Main-Class: altosui.AltosUI' > $@
+ echo "Class-Path: freetts.jar" >> $@
+
+altosui: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="$(libdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@
+ chmod +x $@
+
+altosui-test: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="../libaltos" -jar altosui.jar "$$*"' >> $@
+ chmod +x $@
+
+$(LIBALTOS):
+ -rm -f "$@"
+ $(LN_S) ../libaltos/"$@" .
+
+$(FREETTS_CLASS):
+ -rm -f "$@"
+ $(LN_S) "$(FREETTS)"/"$@" .
+
+$(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA)
+ -rm -f $@
+ -rm -rf linux
+ mkdir -p linux/AltOS
+ cp -p $(LINUX_FILES) linux/AltOS
+ cp -p altosui-fat linux/AltOS/altosui
+ chmod +x linux/AltOS/altosui
+ tar cjf $@ -C linux AltOS
+
+$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA)
+ -rm -f $@
+ -rm -rf macosx
+ mkdir macosx
+ cp -a AltosUI.app macosx/
+ mkdir -p macosx/AltOS macosx/AltosUI.app/Contents/Resources/Java
+ cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar
+ cp -p $(FREETTS_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java
+ cp -p $(MACOSX_EXTRA) macosx/AltOS
+ cd macosx && zip -r ../$@ AltosUI.app AltOS
+
+$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi
+ -rm -f $@
+ makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi
\ No newline at end of file
+++ /dev/null
-Main-Class: altosui.AltosUI
-Class-Path: /usr/share/java/freetts.jar
--- /dev/null
+!addplugindir Instdrv/NSIS/Plugins
+
+Name "Altus Metrum Installer"
+
+; Default install directory
+InstallDir "$PROGRAMFILES\AltusMetrum"
+
+; Tell the installer where to re-install a new version
+InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+
+LicenseText "GNU General Public License Version 2"
+LicenseData "../../COPYING"
+
+; Need admin privs for Vista or Win7
+RequestExecutionLevel admin
+
+ShowInstDetails Show
+
+ComponentText "Altus Metrum Software and Driver Installer"
+
+; Pages to present
+
+Page license
+Page components
+Page directory
+Page instfiles
+
+UninstPage uninstConfirm
+UninstPage instfiles
+
+; And the stuff to install
+
+Section "Install Driver" InstDriver
+ InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} "Altus Metrum"
+ Pop $0
+ DetailPrint "InitDriverSetup: $0"
+
+ InstDrv::DeleteOemInfFiles /NOUNLOAD
+ InstDrv::CreateDevice /NOUNLOAD
+ SetOutPath $TEMP
+ File "../../telemetrum.inf"
+ InstDrv::InstallDriver /NOUNLOAD "$TEMP\telemetrum.inf"
+SectionEnd
+
+Section "AltosUI Application"
+ SetOutPath $INSTDIR
+
+ File "altosui-fat.jar"
+ File "cmudict04.jar"
+ File "cmulex.jar"
+ File "cmu_time_awb.jar"
+ File "cmutimelex.jar"
+ File "cmu_us_kal.jar"
+ File "en_us.jar"
+ File "freetts.jar"
+
+ File "*.dll"
+
+ File "../../icon/*.ico"
+
+ CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico"
+SectionEnd
+
+Section "AltosUI Desktop Shortcut"
+ CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico"
+SectionEnd
+
+Section "TeleMetrum and TeleDongle Firmware"
+
+ SetOutPath $INSTDIR
+
+ File "../../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx"
+ File "../../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
+
+SectionEnd
+
+Section "Uninstaller"
+
+ ; Deal with the uninstaller
+
+ SetOutPath $INSTDIR
+
+ ; Write the install path to the registry
+ WriteRegStr HKLM SOFTWARE\AltusMetrum "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"
+
+ WriteUninstaller "uninstall.exe"
+SectionEnd
+
+Section "Uninstall"
+ DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
+ DeleteRegKey HKLM "Software\AltusMetrum"
+
+ Delete "$INSTDIR\*.*"
+ RMDir "$INSTDIR"
+
+ ; Remove devices
+ InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} "Altus Metrum"
+ InstDrv::DeleteOemInfFiles /NOUNLOAD
+ InstDrv::RemoveAllDevices
+
+ ; Remove shortcuts, if any
+ Delete "$SMPROGRAMS\AltusMetrum.lnk"
+ Delete "$DESKTOP\AltusMetrum.lnk"
+SectionEnd
--- /dev/null
+#!/bin/sh
+me=`which "$0"`
+dir=`dirname "$me"`
+exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar "$@"
--- /dev/null
+.\"
+.\" Copyright © 2010 Bdale Garbee <bdale@gag.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-VIEW 1 "altosui" ""
+.SH NAME
+altosui \- Rocket flight monitor
+.SH SYNOPSIS
+.B "altosui"
+.SH DESCRIPTION
+.I altosui
+connects to a TeleDongle or TeleMetrum device through a USB serial device.
+It provides a user interface to monitor, record and review rocket flight data.
+.SH USAGE
+When connected to a TeleDongle device, altosui turns on the radio
+receiver and listens for telemetry packets. It displays the received
+telemetry data, and reports flight status via voice synthesis. All
+received telemetry information is recorded to a file.
+.P
+When connected to a TeleMetrum device, altosui downloads the eeprom
+data and stores it in a file.
+.SH FILES
+All data log files are recorded into a user-specified directory
+(default ~/AltOS). Files are named using the current date, the serial
+number of the reporting device, the flight number recorded in the data
+and either '.telem' for telemetry data or '.eeprom' for eeprom data.
+.SH "SEE ALSO"
+ao-view(1), ao-load(1), ao-eeprom(1)
+.SH AUTHOR
+Keith Packard
static const struct option options[] = {
{ .name = "tty", .has_arg = 1, .val = 'T' },
{ .name = "device", .has_arg = 1, .val = 'D' },
- { .name = "remote", .has_arg = 1, .val = 'R' },
+ { .name = "remote", .has_arg = 0, .val = 'R' },
{ .name = "channel", .has_arg = 1, .val = 'C' },
{ 0, 0, 0, 0},
};
int invalid;
char serial_line[8192];
- while ((c = getopt_long(argc, argv, "T:D:R", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "T:D:C:R", options, NULL)) != -1) {
switch (c) {
case 'T':
tty = optarg;
--- /dev/null
+*.so
+*.lo
+*.la
+*.java
+*.class
+.libs/
+classlibaltos.stamp
+libaltos_wrap.c
+libaltosJNI
+cjnitest
+libaltos.swig
+swig_bindings/
+++ /dev/null
-OS:=$(shell uname)
-
-#
-# Linux
-#
-ifeq ($(OS),Linux)
-
-JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include
-
-OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS)
-
-OS_LDFLAGS=
-
-LIBNAME=libaltos.so
-EXEEXT=
-
-endif
-
-#
-# Darwin (Mac OS X)
-#
-ifeq ($(OS),Darwin)
-
-OS_CFLAGS=\
- -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \
- --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \
- -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
- -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
- -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-
-OS_LDFLAGS =\
- -framework IOKit -framework CoreFoundation
-
-LIBNAME=libaltos.dylib
-EXEEXT=
-
-endif
-
-#
-# Windows
-#
-ifneq (,$(findstring MINGW,$(OS)))
-
-CC=gcc
-
-OS_CFLAGS = -DWINDOWS -mconsole
-
-OS_LDFLAGS = -lgdi32 -luser32 -lcfgmgr32 -lsetupapi -lole32 \
- -ladvapi32 -lcomctl32 -mconsole -Wl,--add-stdcall-alias
-
-LIBNAME=altos.dll
-
-EXEEXT=.exe
-
-endif
-
-.SUFFIXES: .java .class
-
-CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*"
-
-SWIG_DIR=swig_bindings/java
-SWIG_FILE=$(SWIG_DIR)/libaltos.swig
-SWIG_WRAP=$(SWIG_DIR)/libaltos_wrap.c
-
-JNI_DIR=libaltosJNI
-JNI_FILE=$(JNI_DIR)/libaltosJNI.java
-JNI_SRCS=$(JNI_FILE) \
- $(JNI_DIR)/SWIGTYPE_p_altos_file.java \
- $(JNI_DIR)/SWIGTYPE_p_altos_list.java \
- $(JNI_DIR)/altos_device.java \
- $(JNI_DIR)/libaltos.java
-
-JAVAFILES=\
- $(JNI_SRCS)
-
-CLASSFILES = $(JAVAFILES:%.java=%.class)
-
-JAVAFLAGS=-Xlint:unchecked
-
-CJNITEST=cjnitest$(EXEEXT)
-
-all: $(LIBNAME) $(CJNITEST) $(CLASSFILES)
-
-.java.class:
- javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
-
-CFLAGS=$(OS_CFLAGS) -O0 -g -I.
-
-LDFLAGS=$(OS_LDFLAGS)
-
-HEADERS=libaltos.h
-SRCS = libaltos.c $(SWIG_WRAP)
-OBJS = $(SRCS:%.c=%.o)
-LIBS = $(DARWIN_LIBS)
-
-$(CJNITEST): cjnitest.o $(OBJS)
- cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS)
-
-$(LIBNAME): $(OBJS)
- gcc -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
-
-clean:
- rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o
- rm -rf swig_bindings libaltosJNI
-
-$(JNI_FILE): libaltos.i0 $(HEADERS)
- mkdir -p $(SWIG_DIR)
- mkdir -p libaltosJNI
- sed 's;//%;%;' libaltos.i0 $(HEADERS) > $(SWIG_FILE)
- swig -java -package libaltosJNI $(SWIG_FILE)
- cp swig_bindings/java/*.java libaltosJNI
-
-$(SWIG_WRAP): $(JNI_FILE)
--- /dev/null
+OS:=$(shell uname)
+
+#
+# Linux
+#
+ifeq ($(OS),Linux)
+
+JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include
+
+OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS)
+
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+
+OS_LDFLAGS=
+
+LIBNAME=libaltos.so
+EXEEXT=
+endif
+
+#
+# Darwin (Mac OS X)
+#
+ifeq ($(OS),Darwin)
+
+OS_LIB_CFLAGS=\
+ -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \
+ --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \
+ -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
+ -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
+ -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+
+OS_LDFLAGS =\
+ -framework IOKit -framework CoreFoundation
+
+LIBNAME=libaltos.dylib
+EXEEXT=
+
+endif
+
+#
+# Windows
+#
+ifneq (,$(findstring MINGW,$(OS)))
+
+CC=gcc
+
+OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL
+OS_APP_CFLAGS = -DWINDOWS -mconsole
+
+OS_LDFLAGS = -lgdi32 -luser32 -lcfgmgr32 -lsetupapi -lole32 \
+ -ladvapi32 -lcomctl32 -mconsole -Wl,--add-stdcall-alias
+
+LIBNAME=altos.dll
+
+EXEEXT=.exe
+
+endif
+
+.SUFFIXES: .java .class
+
+CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*"
+
+SWIG_DIR=swig_bindings/java
+SWIG_FILE=$(SWIG_DIR)/libaltos.swig
+SWIG_WRAP=$(SWIG_DIR)/libaltos_wrap.c
+
+JNI_DIR=libaltosJNI
+JNI_FILE=$(JNI_DIR)/libaltosJNI.java
+JNI_SRCS=$(JNI_FILE) \
+ $(JNI_DIR)/SWIGTYPE_p_altos_file.java \
+ $(JNI_DIR)/SWIGTYPE_p_altos_list.java \
+ $(JNI_DIR)/altos_device.java \
+ $(JNI_DIR)/libaltos.java
+
+JAVAFILES=\
+ $(JNI_SRCS)
+
+CLASSFILES = $(JAVAFILES:%.java=%.class)
+
+JAVAFLAGS=-Xlint:unchecked
+
+CJNITEST=cjnitest$(EXEEXT)
+
+all: $(LIBNAME) $(CJNITEST) $(CLASSFILES)
+
+.java.class:
+ javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
+
+CFLAGS=$(OS_LIB_CFLAGS) -O -I.
+
+LDFLAGS=$(OS_LDFLAGS)
+
+HEADERS=libaltos.h
+SRCS = libaltos.c $(SWIG_WRAP)
+OBJS = $(SRCS:%.c=%.o)
+LIBS = $(DARWIN_LIBS)
+
+$(CJNITEST): cjnitest.c $(LIBNAME)
+ $(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS)
+
+$(LIBNAME): $(OBJS)
+ $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
+
+clean:
+ rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o
+ rm -rf swig_bindings libaltosJNI
+
+distclean: clean
+
+$(JNI_FILE): libaltos.i0 $(HEADERS)
+ mkdir -p $(SWIG_DIR)
+ mkdir -p libaltosJNI
+ sed 's;//%;%;' libaltos.i0 $(HEADERS) > $(SWIG_FILE)
+ swig -java -package libaltosJNI $(SWIG_FILE)
+ cp swig_bindings/java/*.java libaltosJNI
+
+$(SWIG_WRAP): $(JNI_FILE)
+
+ifeq ($(OS),Linux)
+install: $(LIBNAME)
+ install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME)
+
+endif
+
+.NOTPARALLEL:
--- /dev/null
+JAVAC=javac
+AM_CFLAGS="-I$(JVM_INCLUDE)"
+AM_JAVACFLAGS=-encoding UTF-8
+
+lib_LTLIBRARIES=libaltos.la
+
+libaltos_la_SOURCES=\
+ libaltos.c
+
+HFILES=libaltos.h
+
+SWIG_FILE=libaltos.swig
+
+CLASSDIR=libaltosJNI
+
+$(SWIG_FILE): libaltos.i0 $(HFILES)
+ sed 's;//%;%;' libaltos.i0 $(HFILES) > $(SWIG_FILE)
+
+all-local: classlibaltos.stamp
+
+classlibaltos.stamp: $(SWIG_FILE)
+ swig -java -package libaltosJNI $(SWIG_FILE)
+ mkdir -p libaltosJNI
+ $(JAVAC) -d . $(AM_JAVACFLAGS) $(JAVACFLAGS) *.java && \
+ touch classlibaltos.stamp
+
+clean-local:
+ -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE)
\ No newline at end of file
continue;
}
altos_puts(file,"v\nc s\n");
+ altos_flush(file);
while ((c = altos_getchar(file, 100)) >= 0) {
putchar (c);
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#define BUILD_DLL
#include "libaltos.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#define USE_POLL
+
PUBLIC int
altos_init(void)
{
}
#ifdef DARWIN
+
+#undef USE_POLL
+
/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
static char *
altos_strndup (const char *s, size_t n)
return 0;
}
+static int
+get_number(io_object_t object, CFStringRef entry, int *result)
+{
+ CFTypeRef entry_as_number;
+ Boolean got_number;
+
+ entry_as_number = IORegistryEntrySearchCFProperty (object,
+ kIOServicePlane,
+ entry,
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively);
+ if (entry_as_number) {
+ got_number = CFNumberGetValue(entry_as_number,
+ kCFNumberIntType,
+ result);
+ if (got_number)
+ return 1;
+ }
+ return 0;
+}
+
struct altos_list *
altos_list_start(void)
{
struct altos_list *list = calloc (sizeof (struct altos_list), 1);
CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
- UInt32 vendor = 0xfffe, product = 0x000a;
- CFNumberRef vendor_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor);
- CFNumberRef product_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product);
io_iterator_t tdIterator;
io_object_t tdObject;
-
- CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBVendorID), vendor_ref);
- CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBProductID), product_ref);
+ kern_return_t ret;
+ int i;
- IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
-
- CFRelease(vendor_ref);
- CFRelease(product_ref);
+ ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
+ if (ret != kIOReturnSuccess)
+ return NULL;
return list;
}
if (!object)
return 0;
+ if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
+ !get_number (object, CFSTR(kUSBProductID), &device->product))
+ continue;
+ if (device->vendor != 0xfffe)
+ continue;
+ if (device->product < 0x000a || 0x0013 < device->product)
+ continue;
if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
- get_string (object, CFSTR("USB Product Name"), device->product, sizeof (device->product)) &&
+ get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
device->serial = atoi(serial_string);
return 1;
struct altos_file {
int fd;
+#ifdef USE_POLL
+ int pipe[2];
+#else
+ int out_fd;
+#endif
unsigned char out_data[USB_BUF_SIZE];
int out_used;
unsigned char in_data[USB_BUF_SIZE];
int in_read;
};
-struct altos_file *
+PUBLIC struct altos_file *
altos_open(struct altos_device *device)
{
struct altos_file *file = calloc (sizeof (struct altos_file), 1);
free(file);
return NULL;
}
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
+ if (file->out_fd < 0) {
+ perror(device->path);
+ close(file->fd);
+ free(file);
+ return NULL;
+ }
+#endif
ret = tcgetattr(file->fd, &term);
if (ret < 0) {
perror("tcgetattr");
close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
free(file);
return NULL;
}
cfmakeraw(&term);
+#ifdef USE_POLL
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+#else
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
+#endif
ret = tcsetattr(file->fd, TCSAFLUSH, &term);
if (ret < 0) {
perror("tcsetattr");
close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
free(file);
return NULL;
}
return file;
}
-void
+PUBLIC void
altos_close(struct altos_file *file)
{
if (file->fd != -1) {
- close(file->fd);
+ int fd = file->fd;
file->fd = -1;
+#ifdef USE_POLL
+ write(file->pipe[1], "\r", 1);
+#else
+ close(file->out_fd);
+ file->out_fd = -1;
+#endif
+ close(fd);
}
}
-void
+PUBLIC void
altos_free(struct altos_file *file)
{
altos_close(file);
free(file);
}
-int
-altos_putchar(struct altos_file *file, char c)
-{
- int ret;
-
- if (file->out_used == USB_BUF_SIZE) {
- ret = altos_flush(file);
- if (ret)
- return ret;
- }
- file->out_data[file->out_used++] = c;
- if (file->out_used == USB_BUF_SIZE)
- return altos_flush(file);
- return 0;
-}
-
-int
+PUBLIC int
altos_flush(struct altos_file *file)
{
+ if (file->out_used && 0) {
+ printf ("flush \"");
+ fwrite(file->out_data, 1, file->out_used, stdout);
+ printf ("\"\n");
+ }
while (file->out_used) {
int ret;
if (file->fd < 0)
return -EBADF;
+#ifdef USE_POLL
ret = write (file->fd, file->out_data, file->out_used);
+#else
+ ret = write (file->out_fd, file->out_data, file->out_used);
+#endif
if (ret < 0)
return -errno;
if (ret) {
file->out_used -= ret;
}
}
+ return 0;
+}
+
+PUBLIC int
+altos_putchar(struct altos_file *file, char c)
+{
+ int ret;
+
+ if (file->out_used == USB_BUF_SIZE) {
+ ret = altos_flush(file);
+ if (ret) {
+ return ret;
+ }
+ }
+ file->out_data[file->out_used++] = c;
+ ret = 0;
+ if (file->out_used == USB_BUF_SIZE)
+ ret = altos_flush(file);
+ return 0;
}
+#ifdef USE_POLL
#include <poll.h>
+#endif
-int
-altos_getchar(struct altos_file *file, int timeout)
+static int
+altos_fill(struct altos_file *file, int timeout)
{
- while (file->in_read == file->in_used) {
- int ret;
+ int ret;
+#ifdef USE_POLL
+ struct pollfd fd[2];
+#endif
- altos_flush(file);
+ if (timeout == 0)
+ timeout = -1;
+ while (file->in_read == file->in_used) {
if (file->fd < 0)
- return -EBADF;
- if (timeout) {
- struct pollfd fd;
- int ret;
- fd.fd = file->fd;
- fd.events = POLLIN;
- ret = poll(&fd, 1, timeout);
- if (ret == 0)
+ return LIBALTOS_ERROR;
+#ifdef USE_POLL
+ fd[0].fd = file->fd;
+ fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
+ fd[1].fd = file->pipe[0];
+ fd[1].events = POLLIN;
+ ret = poll(fd, 2, timeout);
+ if (ret < 0) {
+ perror("altos_getchar");
+ return LIBALTOS_ERROR;
+ }
+ if (ret == 0)
+ return LIBALTOS_TIMEOUT;
+
+ if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
+ return LIBALTOS_ERROR;
+ if (fd[0].revents & POLLIN)
+#endif
+ {
+ ret = read(file->fd, file->in_data, USB_BUF_SIZE);
+ if (ret < 0) {
+ perror("altos_getchar");
+ return LIBALTOS_ERROR;
+ }
+ file->in_read = 0;
+ file->in_used = ret;
+#ifndef USE_POLL
+ if (ret == 0 && timeout > 0)
return LIBALTOS_TIMEOUT;
+#endif
}
- ret = read(file->fd, file->in_data, USB_BUF_SIZE);
- if (ret < 0)
+ }
+ if (file->in_used && 0) {
+ printf ("fill \"");
+ fwrite(file->in_data, 1, file->in_used, stdout);
+ printf ("\"\n");
+ }
+ return 0;
+}
+
+PUBLIC int
+altos_getchar(struct altos_file *file, int timeout)
+{
+ int ret;
+ while (file->in_read == file->in_used) {
+ if (file->fd < 0)
return LIBALTOS_ERROR;
- file->in_read = 0;
- file->in_used = ret;
+ ret = altos_fill(file, timeout);
+ if (ret)
+ return ret;
}
return file->in_data[file->in_read++];
}
#ifdef WINDOWS
+#include <stdlib.h>
#include <windows.h>
#include <setupapi.h>
unsigned char in_data[USB_BUF_SIZE];
int in_used;
int in_read;
+ OVERLAPPED ov_read;
+ BOOL pend_read;
+ OVERLAPPED ov_write;
};
-
PUBLIC struct altos_list *
altos_list_start(void)
{
SP_DEVINFO_DATA dev_info_data;
char port[128];
DWORD port_len;
- char location[256];
+ char friendlyname[256];
char symbolic[256];
DWORD symbolic_len;
HKEY dev_key;
int vid, pid;
int serial;
HRESULT result;
- DWORD location_type;
- DWORD location_len;
+ DWORD friendlyname_type;
+ DWORD friendlyname_len;
dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
"%d", &serial);
if (!USB_IS_ALTUSMETRUM(vid, pid)) {
- printf("Not Altus Metrum symbolic name: %s\n",
- symbolic);
RegCloseKey(dev_key);
continue;
}
continue;
}
- /* Fetch the 'location information' which is the device name,
- * at least on XP */
- location_len = sizeof (location);
+ /* Fetch the device description which is the device name,
+ * with firmware that has unique USB ids */
+ friendlyname_len = sizeof (friendlyname);
if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
&dev_info_data,
- SPDRP_LOCATION_INFORMATION,
- &location_type,
- (BYTE *)location,
- sizeof(location),
- &location_len))
+ SPDRP_FRIENDLYNAME,
+ &friendlyname_type,
+ (BYTE *)friendlyname,
+ sizeof(friendlyname),
+ &friendlyname_len))
{
- printf("Failed to get location\n");
+ printf("Failed to get friendlyname\n");
continue;
}
device->vendor = vid;
device->product = pid;
device->serial = serial;
-
- if (strcasestr(location, "tele"))
- strcpy(device->name, location);
- else
- strcpy(device->name, "");
+ strcpy(device->name, friendlyname);
strcpy(device->path, port);
- printf ("product: %04x:%04x (%s) path: %s serial %d\n",
- device->vendor, device->product, device->name,
- device->path, device->serial);
return 1;
}
result = GetLastError();
}
static int
-altos_fill(struct altos_file *file, int timeout)
+altos_queue_read(struct altos_file *file)
{
- DWORD result;
DWORD got;
- COMMTIMEOUTS timeouts;
-
- if (file->in_read < file->in_used)
+ if (file->pend_read)
return LIBALTOS_SUCCESS;
- file->in_read = file->in_used = 0;
- if (timeout) {
- timeouts.ReadIntervalTimeout = MAXDWORD;
- timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
- timeouts.ReadTotalTimeoutConstant = timeout;
+ if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
+ if (GetLastError() != ERROR_IO_PENDING)
+ return LIBALTOS_ERROR;
+ file->pend_read = TRUE;
} else {
- timeouts.ReadIntervalTimeout = 0;
- timeouts.ReadTotalTimeoutMultiplier = 0;
- timeouts.ReadTotalTimeoutConstant = 0;
+ file->pend_read = FALSE;
+ file->in_read = 0;
+ file->in_used = got;
}
- timeouts.WriteTotalTimeoutMultiplier = 0;
- timeouts.WriteTotalTimeoutConstant = 0;
+ return LIBALTOS_SUCCESS;
+}
- if (!SetCommTimeouts(file->handle, &timeouts)) {
- printf("SetCommTimeouts failed %d\n", GetLastError());
- }
+static int
+altos_wait_read(struct altos_file *file, int timeout)
+{
+ DWORD ret;
+ DWORD got;
+
+ if (!file->pend_read)
+ return LIBALTOS_SUCCESS;
- if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, NULL)) {
- result = GetLastError();
- printf ("read failed %d\n", result);
+ if (!timeout)
+ timeout = INFINITE;
+
+ ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE))
+ return LIBALTOS_ERROR;
+ file->pend_read = FALSE;
+ file->in_read = 0;
+ file->in_used = got;
+ break;
+ case WAIT_TIMEOUT:
+ return LIBALTOS_TIMEOUT;
+ break;
+ default:
return LIBALTOS_ERROR;
- got = 0;
}
- if (got)
+ return LIBALTOS_SUCCESS;
+}
+
+static int
+altos_fill(struct altos_file *file, int timeout)
+{
+ int ret;
+
+ if (file->in_read < file->in_used)
return LIBALTOS_SUCCESS;
- return LIBALTOS_TIMEOUT;
+
+ file->in_read = file->in_used = 0;
+
+ ret = altos_queue_read(file);
+ if (ret)
+ return ret;
+ ret = altos_wait_read(file, timeout);
+ if (ret)
+ return ret;
+
+ return LIBALTOS_SUCCESS;
}
PUBLIC int
DWORD put;
char *data = file->out_data;
char used = file->out_used;
- DWORD result;
+ DWORD ret;
while (used) {
- if (!WriteFile(file->handle, data, used, &put, NULL)) {
- result = GetLastError();
- printf ("write failed %d\n", result);
- return LIBALTOS_ERROR;
+ if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
+ if (GetLastError() != ERROR_IO_PENDING)
+ return LIBALTOS_ERROR;
+ ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE))
+ return LIBALTOS_ERROR;
+ break;
+ default:
+ return LIBALTOS_ERROR;
+ }
}
data += put;
used -= put;
PUBLIC struct altos_file *
altos_open(struct altos_device *device)
{
- struct altos_file *file = calloc (sizeof (struct altos_file), 1);
+ struct altos_file *file = calloc (1, sizeof (struct altos_file));
char full_name[64];
+ DCB dcbSerialParams = {0};
+ COMMTIMEOUTS timeouts;
if (!file)
return NULL;
strcat(full_name, device->path);
file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
+ FILE_FLAG_OVERLAPPED, NULL);
if (file->handle == INVALID_HANDLE_VALUE) {
free(file);
return NULL;
}
+ file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
- timeouts.ReadTotalTimeoutConstant = 100;
+ timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
timeouts.WriteTotalTimeoutMultiplier = 0;
- timeouts.WriteTotalTimeoutConstant = 10000;
- if (!SetCommTimeouts(file->handle, &timeouts)) {
- printf("SetCommTimeouts failed %d\n", GetLastError());
+ timeouts.WriteTotalTimeoutConstant = 0;
+ SetCommTimeouts(file->handle, &timeouts);
+
+ dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
+ if (!GetCommState(file->handle, &dcbSerialParams)) {
+ CloseHandle(file->handle);
+ free(file);
+ return NULL;
+ }
+ dcbSerialParams.BaudRate = CBR_9600;
+ dcbSerialParams.ByteSize = 8;
+ dcbSerialParams.StopBits = ONESTOPBIT;
+ dcbSerialParams.Parity = NOPARITY;
+ if (!SetCommState(file->handle, &dcbSerialParams)) {
+ CloseHandle(file->handle);
+ free(file);
+ return NULL;
}
return file;
{
int ret;
while (file->in_read == file->in_used) {
- ret = altos_flush(file);
- if (ret)
- return ret;
if (file->handle == INVALID_HANDLE_VALUE)
return LIBALTOS_ERROR;
ret = altos_fill(file, timeout);
#ifndef _LIBALTOS_H_
#define _LIBALTOS_H_
+#include <stdlib.h>
+
#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# ifndef BUILD_STATIC
# ifdef BUILD_DLL
dnl
dnl Process this file with autoconf to create configure.
-AC_INIT(COPYING)
-
-AM_INIT_AUTOMAKE(altos, 0.1)
+AC_PREREQ(2.57)
+AC_INIT([altos], 0.7.1)
+AC_CONFIG_SRCDIR([src/ao.h])
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
+VERSION_DASH=`echo $VERSION | sed 's/\./-/g'`
+AC_SUBST(VERSION_DASH)
+
dnl ==========================================================================
AM_CONFIG_HEADER(config.h)
+AC_ARG_WITH(freetts, AS_HELP_STRING([--with-freetts=PATH],
+ [Set freetts class path (default /usr/share/java)]),
+ [FREETTS=$withval], [FREETTS=/usr/share/java])
+
+AC_SUBST(FREETTS)
+
+AC_ARG_WITH(jvm, AS_HELP_STRING([--with-jvm-include=PATH],
+ [Set jvm include path for jni builds (default searches in /usr/lib/jvm)]),
+ [JVM_INCLUDE=$withval], [JVM_INCLUDE=auto])
+
+if test "x$JVM_INCLUDE" = "xauto"; then
+ AC_MSG_CHECKING([JVM include files])
+ for jvm in default-java java-6-openjdk java-6-sun; do
+ if test "x$JVM_INCLUDE" = "xauto"; then
+ INCLUDE="/usr/lib/jvm/$jvm/include"
+ if test -f "$INCLUDE"/jni.h; then
+ JVM_INCLUDE="$INCLUDE"
+ fi
+ fi
+ done
+ if test "x$JVM_INCLUDE" = "xauto"; then
+ AC_MSG_ERROR([no JVM include files found])
+ fi
+ AC_MSG_RESULT([$JVM_INCLUDE])
+fi
+
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
-AC_PROG_RANLIB
+AC_PROG_LIBTOOL
PKG_PROG_PKG_CONFIG
CFLAGS="-g"
ao-tools/ao-load/Makefile
ao-tools/ao-postflight/Makefile
ao-tools/ao-view/Makefile
+ao-tools/libaltos/Makefile
+ao-tools/altosui/Makefile
ao-utils/Makefile
+src/Version
])
[Desktop Entry]
Type=Application
-Name=AltOS View
+Name=AltOS UI
GenericName=TeleMetrum Telemetry Viewer
Comment=View and log downlink data from TeleMetrum
Icon=/usr/share/pixmaps/altusmetrum.xpm
-Exec=/usr/bin/ao-view %f
+Exec=/usr/bin/altosui %f
Terminal=false
MimeType=text/plain;
Categories=Education;Science;
+altos (0.7+53+g59798c6) unstable; urgency=low
+
+ [ Keith Packard ]
+ * altosui: Abort flashing if debug port isn't working
+ * altosui: allow flashing to be canceled from the rom config dialog
+ * altosui: Hide internal rom config UI helper function
+ * altosui: Remove some debug printfs from AltosRomconfig class
+ * altosui: Post error dialog on invalid ROM config values.
+ * altosui: build Mac OS .zip file to include paths
+ * altosui: Report telemetry CRC errors in UI
+ * altosui: Deal with altos bug setting radio channel while monitoring
+ * altosui: Allow 'connect to device' when already connected
+ * Revert "altosui: Deal with altos bug setting radio channel while
+ monitoring"
+ * altosui: Must flush serial line after configuring for telemetry
+ * altosui: Catch I/O errors on telemetry device, report to user
+
+ -- Bdale Garbee <bdale@gag.com> Sat, 04 Sep 2010 00:46:12 -0400
+
+altos (0.7+40+g59a40f6) unstable; urgency=low
+
+ [ Bdale Garbee ]
+ * add distclean targets to libaltos and altosui to all Debian package
+ to build, and clean up other distclean content as needed
+
+ [ Keith Packard ]
+ * altosui: missed AltosReader.class in the Makefile
+ * altos: Bounds check Skytraq GPS tracking data array
+ * altosui: Remove Manifest.txt from git repo as it's built now
+
+ -- Bdale Garbee <bdale@gag.com> Thu, 02 Sep 2010 00:44:15 -0400
+
+altos (0.7+28+gd006c5e) unstable; urgency=low
+
+ * add runtime dependencies for altos binary package
+
+ -- Bdale Garbee <bdale@gag.com> Tue, 31 Aug 2010 00:20:00 -0400
+
+altos (0.7+26+gc35632e) unstable; urgency=low
+
+ * don't build all the "fat" jar deliverables by default
+
+ -- Bdale Garbee <bdale@gag.com> Mon, 30 Aug 2010 19:37:40 -0600
+
+altos (0.7+23+g25764fc) unstable; urgency=low
+
+ [ Bdale Garbee ]
+ * fix up for an 0.7 release
+ * update changelogs for Debian build
+
+ [ Keith Packard ]
+ * libaltos: AltusMetrum devices use more than one USB ID.
+ * altosui: provide separate flush_input/flush_output for serial. deal
+ with monitor automatically
+ * altosui: discard invalid lines while reading Eeprom flight data
+ * libaltos: Mac OS X cannot use 'poll(2)' on serial lines.
+ * libaltos: Missing OS_LDFLAGS on cjnitest build
+ * libaltos: cjnitest needs altos_flush now
+ * altos: flush pending output when terminating packet mode
+ * altos: Abort radio harder when terminating packet mode.
+ * altos: shut down packet mode cleanly
+ * libaltos: Fix windows build.
+ * libaltos: Improve Makefile
+ * Update telemetrum.inf to include all current USB ids.
+ * libaltos: Add pre-built Mac OS X libaltos.dylib
+ * libaltos: Add pre-built Windows .dll
+ * altos: Windows sends USB Out packets of 0 length. Ack them.
+ * libaltos: Use overlapped I/O on windows
+ * altosui: Build linux, mac and windows archives on Linux
+ * altosui: build debian-style altosui too
+ * altosui: Devices with USB id 0x000a always get listed
+
+ [ Bdale Garbee ]
+ * continue even if rm's don't have anything to do
+ * make invocation of 'install' pathless to work on more Unix variants
+ * add a .gitattributes file, configuring the Mac and Windows binary
+ library
+
+ -- Bdale Garbee <bdale@gag.com> Mon, 30 Aug 2010 19:07:13 -0600
+
+altos (0.7) unstable; urgency=low
+
+ * update changelogs for Debian build
+ * fix up for an 0.7 release
+
+ -- Bdale Garbee <bdale@gag.com> Fri, 27 Aug 2010 22:25:38 -0600
+
+altos (0.6+375+g0bd4cc0) unstable; urgency=low
+
+ * fix path to installed shared library
+
+ -- Bdale Garbee <bdale@gag.com> Fri, 27 Aug 2010 13:13:14 -0600
+
+altos (0.6+373+gcf65c6b) unstable; urgency=low
+
+ [ Keith Packard ]
+ * altosui: rename AltosEeprom -> AltosEepromDownload, split out Altos
+ constants
+ * altosui: Capture config and version info in .eeprom files
+ * altosui: Merge gps date and time classes into gps class
+ * altosui: Clear displayed data rows as needed.
+ * altosui: Split status and info panels into separate files
+ * altosui: Explicitly initialize Altos class
+ * altosui: Split flight record out of telemetry class
+ * altosui: Compute flight state from eeprom data
+ * altosui: Add comments to Eeprom reader
+ * altos: add callsign to packet mode, increase payload to 64 bytes
+ * altosui: Start adding code to write csv files from eeprom/telem
+ files
+ * ao-dumplog: add --channel option (for use with -R option)
+ * libaltos: integrate Windows support.
+ * altosui: Select devices by USB vendor/product ID.
+ * altos: Define USB product ID in per-product Makefile.defs file
+ * altosui: Make teledongle callsign configurable
+ * altosui: Add TeleMetrum configuration
+ * altosui: Set callsign when fetching eeprom data over the air
+
+ [ Bdale Garbee ]
+ * add freetts as a build dep
+ * working on java packaging details
+
+ [ Keith Packard ]
+ * altosui: Add .ihx file reading code and stub out flashing UI
+ * altosui: Add debug dongle API, split flash UI out
+ * ao-dumplog: Fix --remote and --channel options to actually work
+ * altosui: pad TM config dialog values to avoid clipping descenders
+ * libaltos: use pipe to wake up getchar on close. use mutexes
+ * altosui: Add lots more cc1111 debug interface functions
+ * altosui: remove debug printf from AltosHexfile
+ * altosui: flush serial output before waiting for reply
+ * altosui: Remove debug printf from AltosRomconfig
+ * altosui: Finish device programming code
+ * altos: Place rom config variables in fixed location
+ * altosui: make default Manifest look for built-in freetts
+ * altosui: Separate out log file choosing dialog to share with CSV
+ generator
+ * altosui: refactor logfile chooser dialog to share more code
+ * altosui: Add ability to create CSV file from telem or eeprom files
+ * altosui: disable radio monitoring while using serial line for
+ debugging
+ * altosui: Delay mapping Flash UI until flashing actually starts
+ * altosui: fetch existing romconfig for flashing
+ * altosui: always display romconfig ui while flashing
+ * altosui: write USB serial number string while flashing
+ * altosui: flush replies from serial link when entering debug mode
+ * altos: always rebuild ao_product.c to track git version
+ * altos: print GPS state flags in GPS 'g' command
+ * altos: mark gps date written only after it gets into eeprom
+ * altosui: Move number parsing code to Altos general class
+ * altosui: Add AltosGreatCircle constructors
+ * altosui: add rssi and distance/dir from pad to CSV files
+ * altosui: AltosEepromReader was mis-setting boost tick
+ * altosui: Add support for old (version < 3) telemetry files
+ * altosui: Serial line is in UTF-8 encoding. Deal with it.
+ * altosui: When parsing saved telem files, errors shouldn't abort file
+ * altosui: Remove debug printf from AltosState.java
+ * altosui: command line args are converted to csv format
+ * altos: prepare for sdcc 2.9.1
+
+ [ Bdale Garbee ]
+ * add a dummy install target
+ * lose the prebuild hook for now while I'm fumbling
+ * add install target for libaltos
+ * add an install target for altosui
+
+ [ Keith Packard ]
+ * altosui: add elevation and range information
+
+ [ Bdale Garbee ]
+ * fix up the wrapper's path to the jar file
+ * update Debian standards version
+ * fix permissions on installed jar file, switch from ao-view to
+ altosui in
+ * install altosui man page
+ * fix man page delivery path
+ * Revert "lose the prebuild hook for now while I'm fumbling"
+
+ -- Bdale Garbee <bdale@gag.com> Fri, 27 Aug 2010 12:40:04 -0600
+
altos (0.6+303+gb6da90b) unstable; urgency=low
* add freetts as a build dep
Maintainer: Bdale Garbee <bdale@gag.com>
Uploaders: Keith Packard <keithp@keithp.com>
Build-Depends: debhelper (>= 7), autoconf, automake, flite1-dev, gawk, libasound2-dev, libgconf2-dev, libglade2-dev, libgtk2.0-dev, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, libplplot-dev, xsltproc, fop, docbook-xml, docbook-xsl, libsndfile1-dev, swig, openjdk-6-jdk, freetts
-Standards-Version: 3.9.0
+Standards-Version: 3.9.1
Homepage: http://altusmetrum.org/AltOS
Package: altos
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, nickle, plplot9-driver-cairo
+Depends: ${shlibs:Depends}, ${misc:Depends}, default-jre | java2-runtime, freetts, nickle, plplot9-driver-cairo
Suggests: slim | gdm
Replaces: altusmetrum-themes, slim-altusmetrum
Conflicts: altusmetrum-themes, slim-altusmetrum
etc/apt/sources.list.d
usr/bin
+usr/lib/altos
usr/share/altos
usr/share/applications
usr/share/gdm/themes/altusmetrum
+usr/share/java
usr/share/pixmaps
usr/share/slim/themes/altusmetrum
clean:
rm -f telemetrum-doc.html telemetrum-doc.pdf telemetrum-doc.fo
+distclean:
+ rm -f telemetrum-doc.html telemetrum-doc.pdf telemetrum-doc.fo
+
indent: telemetrum-doc.xsl
xmlindent -i 2 < telemetrum-doc.xsl > telemetrum-doc.new
#
CC=sdcc
+include Version
+
SUBDIRS=telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test
all: all-recursive
CC=sdcc
ifndef VERSION
-VERSION=$(shell git describe)
+include ../Version
endif
CFLAGS=--model-small --debug --opt-code-speed
ao_panic.c \
ao_task.c \
ao_timer.c \
+ ao_romconfig.c \
_bp.c
#
../altitude.h: make-altitude
nickle $< > $@
-ao_product.h: ao-make-product.5c
+ao_product.h: ao-make-product.5c ../Version
$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
ao_product.rel: ao_product.c ao_product.h
--- /dev/null
+VERSION=@VERSION@
/* Yield the processor to another task */
void
-ao_yield(void) _naked;
+ao_yield(void) __naked;
/* Add a task to the run queue */
void
/* Timer interrupt */
void
-ao_timer_isr(void) interrupt 9;
+ao_timer_isr(void) __interrupt 9;
/* Initialize the timer */
void
/* The A/D interrupt handler */
void
-ao_adc_isr(void) interrupt 1;
+ao_adc_isr(void) __interrupt 1;
/* Initialize the A/D converter */
void
void
ao_led_init(uint8_t enable);
+/*
+ * ao_romconfig.c
+ */
+
+#define AO_ROMCONFIG_VERSION 2
+
+extern __code __at (0x00a0) uint16_t ao_romconfig_version;
+extern __code __at (0x00a2) uint16_t ao_romconfig_check;
+extern __code __at (0x00a4) uint16_t ao_serial_number;
+extern __code __at (0x00a6) uint32_t ao_radio_cal;
+extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
+
/*
* ao_usb.c
*/
/* USB interrupt handler */
void
-ao_usb_isr(void) interrupt 6;
+ao_usb_isr(void) __interrupt 6;
/* Enable the USB controller */
void
/* DMA interrupt routine */
void
-ao_dma_isr(void) interrupt 8;
+ao_dma_isr(void) __interrupt 8;
/*
* ao_mutex.c
uint8_t year;
uint8_t month;
uint8_t day;
+ uint8_t extra;
} gps_date;
struct {
uint16_t d0;
};
/* Write a record to the eeprom log */
-void
+uint8_t
ao_log_data(__xdata struct ao_log_record *log) __reentrant;
/* Flush the log */
#if HAS_SERIAL_1
void
-ao_serial_rx1_isr(void) interrupt 3;
+ao_serial_rx1_isr(void) __interrupt 3;
void
-ao_serial_tx1_isr(void) interrupt 14;
+ao_serial_tx1_isr(void) __interrupt 14;
char
ao_serial_getchar(void) __critical;
uint8_t c_n_1;
};
+#define AO_MAX_GPS_TRACKING 12
+
struct ao_gps_tracking_data {
uint8_t channels;
- struct ao_gps_sat_data sats[12];
+ struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING];
};
extern __xdata uint8_t ao_gps_mutex;
extern __xdata uint8_t ao_radio_mutex;
void
-ao_radio_general_isr(void) interrupt 16;
+ao_radio_general_isr(void) __interrupt 16;
void
ao_radio_get(void);
* each instance of a product
*/
-extern const uint8_t ao_usb_descriptors [];
-extern const uint16_t ao_serial_number;
+extern __code __at(0x00aa) uint8_t ao_usb_descriptors [];
extern const char ao_version[];
extern const char ao_manufacturer[];
extern const char ao_product[];
}
void
-ao_adc_isr(void) interrupt 1
+ao_adc_isr(void) __interrupt 1
{
uint8_t sequence;
uint8_t __xdata *a;
}
void
-ao_cmd(void *parameters)
+ao_cmd(void)
{
__xdata char c;
__xdata uint8_t cmd, cmds;
__code struct ao_cmds * __xdata cs;
void (*__xdata func)(void);
- (void) parameters;
lex_echo = 1;
for (;;) {
#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL"
#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000
#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0
-/*
- * For 434.550MHz, the frequency value is:
- *
- * 434.550e6 / (24e6 / 2**16) = 1186611.2
- *
- * This value is stored in a const variable so that
- * ao-load can change it during programming for
- * devices that have no eeprom for config data.
- */
-const uint32_t ao_radio_cal = 1186611;
#if HAS_EEPROM
static void
}
void
-ao_dma_isr(void) interrupt 8
+ao_dma_isr(void) __interrupt 8
{
uint8_t id, mask;
gps_log.u.gps_altitude.unused = 0xffff;
ao_log_data(&gps_log);
if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {
- date_reported = 1;
gps_log.type = AO_LOG_GPS_DATE;
gps_log.u.gps_date.year = gps_data.year;
gps_log.u.gps_date.month = gps_data.month;
gps_log.u.gps_date.day = gps_data.day;
- ao_log_data(&gps_log);
+ gps_log.u.gps_date.extra = 0;
+ date_reported = ao_log_data(&gps_log);
}
}
}
ao_gps_skip_field(); /* sats in view */
while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') {
i = ao_gps_tracking_next.channels;
- ao_gps_tracking_next.sats[i].svid = ao_gps_decimal(2); /* SVID */
+ c = ao_gps_decimal(2); /* SVID */
+ if (i < AO_MAX_GPS_TRACKING)
+ ao_gps_tracking_next.sats[i].svid = c;
ao_gps_lexchar();
ao_gps_skip_field(); /* elevation */
ao_gps_lexchar();
ao_gps_skip_field(); /* azimuth */
- if (!(ao_gps_tracking_next.sats[i].c_n_1 = ao_gps_decimal(2))) /* C/N0 */
- ao_gps_tracking_next.sats[i].svid = 0;
- ao_gps_tracking_next.channels = i + 1;
+ c = ao_gps_decimal(2); /* C/N0 */
+ if (i < AO_MAX_GPS_TRACKING) {
+ if (!(ao_gps_tracking_next.sats[i].c_n_1 = c))
+ ao_gps_tracking_next.sats[i].svid = 0;
+ ao_gps_tracking_next.channels = i + 1;
+ }
}
if (ao_gps_char == '*') {
uint8_t cksum = ao_gps_cksum ^ '*';
printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);
printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude);
printf ("Alt: %d\n", ao_gps_data.altitude);
+ printf ("Flags: 0x%x\n", ao_gps_data.flags);
ao_mutex_put(&ao_gps_mutex);
}
uint8_t c_n_1;
};
+#define AO_MAX_GPS_TRACKING 12
+
struct ao_gps_tracking_data {
uint8_t channels;
- struct ao_gps_sat_data sats[12];
+ struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING];
};
void
uint8_t c_n_1;
};
+#define AO_MAX_GPS_TRACKING 12
+
struct ao_gps_tracking_data {
uint8_t channels;
- struct ao_gps_sat_data sats[12];
+ struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING];
};
void
return -sum;
}
-void
+uint8_t
ao_log_data(__xdata struct ao_log_record *log) __reentrant
{
+ uint8_t wrote = 0;
/* set checksum */
log->csum = 0;
log->csum = ao_log_csum((__xdata uint8_t *) log);
ao_mutex_get(&ao_log_mutex); {
if (ao_log_running) {
+ wrote = 1;
ao_ee_write(ao_log_current_pos,
(uint8_t *) log,
sizeof (struct ao_log_record));
ao_log_running = 0;
}
} ao_mutex_put(&ao_log_mutex);
+ return wrote;
}
void
ao_wake_task(&ao_packet_task);
ao_usb_flush();
ao_sleep(&ao_stdin_ready);
+ if (!ao_packet_enable)
+ break;
}
return c;
}
if (c == '\r') c = '\n';
ao_packet_putchar(c);
}
+
+ /* Wait for a second if there is any pending data */
+ for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++)
+ ao_delay(AO_MS_TO_TICKS(100));
ao_packet_enable = 0;
- ao_radio_abort();
while (ao_packet_echo_task.wchan || ao_packet_task.wchan) {
- ao_wake_task(&ao_packet_echo_task);
- ao_wake_task(&ao_packet_task);
- ao_yield();
+ if (ao_packet_echo_task.wchan)
+ ao_wake_task(&ao_packet_echo_task);
+ ao_delay(AO_MS_TO_TICKS(10));
}
}
/* Defines which mark this particular AltOS product */
-const uint16_t ao_serial_number = AO_iSerial_NUMBER;
const char ao_version[] = AO_iVersion_STRING;
const char ao_manufacturer[] = AO_iManufacturer_STRING;
const char ao_product[] = AO_iProduct_STRING;
#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))
/* USB descriptors in one giant block of bytes */
-const uint8_t ao_usb_descriptors [] =
+__code __at(0x00aa) uint8_t ao_usb_descriptors [] =
{
/* Device descriptor */
0x12,
__xdata uint8_t ao_radio_mutex;
void
-ao_radio_general_isr(void) interrupt 16
+ao_radio_general_isr(void) __interrupt 16
{
S1CON &= ~0x03;
if (RFIF & RFIF_IM_TIMEOUT) {
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__code __at (0x00a0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION;
+__code __at (0x00a2) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION;
+__code __at (0x00a4) uint16_t ao_serial_number = 0;
+/*
+ * For 434.550MHz, the frequency value is:
+ *
+ * 434.550e6 / (24e6 / 2**16) = 1186611.2
+ *
+ * This value is stored in a const variable so that
+ * ao-load can change it during programming for
+ * devices that have no eeprom for config data.
+ */
+__code __at (0x00a6) uint32_t ao_radio_cal = 1186611;
volatile __xdata struct ao_fifo ao_usart1_tx_fifo;
void
-ao_serial_rx1_isr(void) interrupt 3
+ao_serial_rx1_isr(void) __interrupt 3
{
if (!ao_fifo_full(ao_usart1_rx_fifo))
ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF);
}
void
-ao_serial_tx1_isr(void) interrupt 14
+ao_serial_tx1_isr(void) __interrupt 14
{
UTX1IF = 0;
ao_serial_tx1_started = 0;
volatile __data uint8_t ao_adc_count;
#endif
-void ao_timer_isr(void) interrupt 9
+void ao_timer_isr(void) __interrupt 9
{
++ao_tick_count;
#if HAS_ADC
* so when we hook that up, fix this
*/
void
-ao_usb_isr(void) interrupt 6
+ao_usb_isr(void) __interrupt 6
{
USBIF = 0;
ao_usb_iif |= USBIIF;
if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0)
return AO_READ_AGAIN;
ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL;
- if (ao_usb_out_bytes == 0)
+ if (ao_usb_out_bytes == 0) {
+ USBINDEX = AO_USB_OUT_EP;
+ USBCSOL &= ~USBCSOL_OUTPKT_RDY;
return AO_READ_AGAIN;
+ }
}
--ao_usb_out_bytes;
c = USBFIFO[AO_USB_OUT_EP << 1];
#include <cc1110.h>
#include <stdint.h>
-sfr at 0xA8 IEN0; /* Interrupt Enable 0 Register */
+sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */
-sbit at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */
-sbit at 0xA9 ADCIE; /* ADC interrupt enable */
-sbit at 0xAA URX0IE; /* USART0 RX interrupt enable */
-sbit at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */
-sbit at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */
-sbit at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */
-sbit at 0xAD STIE; /* Sleep Timer interrupt enable */
-sbit at 0xAF EA; /* Enable All */
+sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */
+sbit __at 0xA9 ADCIE; /* ADC interrupt enable */
+sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */
+sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */
+sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */
+sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */
+sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */
+sbit __at 0xAF EA; /* Enable All */
#define IEN0_EA (1 << 7)
#define IEN0_STIE (1 << 5)
#define IEN0_ADCIE (1 << 1)
#define IEN0_RFTXRXIE (1 << 0)
-sfr at 0xB8 IEN1; /* Interrupt Enable 1 Register */
+sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */
#define IEN1_P0IE (1 << 5) /* Port 0 interrupt enable */
#define IEN1_T4IE (1 << 4) /* Timer 4 interrupt enable */
#define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */
/* IEN2 */
-sfr at 0x9A IEN2; /* Interrupt Enable 2 Register */
+sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */
#define IEN2_WDTIE (1 << 5) /* Watchdog timer interrupt enable */
#define IEN2_P1IE (1 << 4) /* Port 1 interrupt enable */
#define IEN2_RFIE (1 << 0) /* RF general interrupt enable */
/* CLKCON 0xC6 */
-sfr at 0xC6 CLKCON; /* Clock Control */
+sfr __at 0xC6 CLKCON; /* Clock Control */
#define CLKCON_OSC32K_RC (1 << 7)
#define CLKCON_OSC32K_XTAL (0 << 7)
#define SLEEP_MODE_MASK (3 << 0)
/* PCON 0x87 */
-sfr at 0x87 PCON; /* Power Mode Control Register */
+sfr __at 0x87 PCON; /* Power Mode Control Register */
#define PCON_IDLE (1 << 0)
/*
* TCON
*/
-sfr at 0x88 TCON; /* CPU Interrupt Flag 1 */
+sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */
-sbit at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */
-sbit at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */
-sbit at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */
-sbit at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */
-sbit at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */
+sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */
+sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */
+sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */
+sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */
+sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */
#define TCON_URX1IF (1 << 7)
#define TCON_I2SRXIF (1 << 7)
/*
* S0CON
*/
-sfr at 0x98 S0CON; /* CPU Interrupt Flag 2 */
+sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */
-sbit at 0x98 ENCIF_0; /* AES interrupt 0. */
-sbit at 0x99 ENCIF_1; /* AES interrupt 1. */
+sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */
+sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */
#define S0CON_ENCIF_1 (1 << 1)
#define S0CON_ENCIF_0 (1 << 0)
/*
* S1CON
*/
-sfr at 0x9B S1CON; /* CPU Interrupt Flag 3 */
+sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */
#define S1CON_RFIF_1 (1 << 1)
#define S1CON_RFIF_0 (1 << 0)
/*
* IRCON
*/
-sfr at 0xC0 IRCON; /* CPU Interrupt Flag 4 */
+sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */
-sbit at 0xC0 DMAIF; /* DMA complete interrupt flag */
-sbit at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */
-sbit at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */
-sbit at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */
-sbit at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */
-sbit at 0xC5 P0IF; /* Port0 interrupt flag */
-sbit at 0xC7 STIF; /* Sleep Timer interrupt flag */
+sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */
+sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */
+sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */
+sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */
+sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */
+sbit __at 0xC5 P0IF; /* Port0 interrupt flag */
+sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */
#define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */
#define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */
/*
* IRCON2
*/
-sfr at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */
+sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */
-sbit at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */
-sbit at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */
-sbit at 0xE9 UTX0IF; /* USART0 TX interrupt flag */
-sbit at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */
-sbit at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */
-sbit at 0xEB P1IF; /* Port1 interrupt flag */
-sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */
+sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */
+sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */
+sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */
+sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */
+sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */
+sbit __at 0xEB P1IF; /* Port1 interrupt flag */
+sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */
#define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */
#define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */
* Priority = (IP1 << 1) | IP0. Higher priority interrupts served first
*/
-sfr at 0xB9 IP1; /* Interrupt Priority 1 */
-sfr at 0xA9 IP0; /* Interrupt Priority 0 */
+sfr __at 0xB9 IP1; /* Interrupt Priority 1 */
+sfr __at 0xA9 IP0; /* Interrupt Priority 0 */
#define IP1_IPG5 (1 << 5)
#define IP1_IPG4 (1 << 4)
*/
/* Timer count */
-sfr at 0xCA T3CNT;
-sfr at 0xEA T4CNT;
+sfr __at 0xCA T3CNT;
+sfr __at 0xEA T4CNT;
/* Timer control */
-sfr at 0xCB T3CTL;
-sfr at 0xEB T4CTL;
+sfr __at 0xCB T3CTL;
+sfr __at 0xEB T4CTL;
#define TxCTL_DIV_1 (0 << 5)
#define TxCTL_DIV_2 (1 << 5)
/* Timer 4 channel 0 compare control */
-sfr at 0xCC T3CCTL0;
-sfr at 0xCE T3CCTL1;
-sfr at 0xEC T4CCTL0;
-sfr at 0xEE T4CCTL1;
+sfr __at 0xCC T3CCTL0;
+sfr __at 0xCE T3CCTL1;
+sfr __at 0xEC T4CCTL0;
+sfr __at 0xEE T4CCTL1;
#define TxCCTLy_IM (1 << 6)
#define TxCCTLy_CMP_SET (0 << 3)
#define TxCCTLy_CMP_MODE_ENABLE (1 << 2)
/* Timer compare value */
-sfr at 0xCD T3CC0;
-sfr at 0xCF T3CC1;
-sfr at 0xED T4CC0;
-sfr at 0xEF T4CC1;
+sfr __at 0xCD T3CC0;
+sfr __at 0xCF T3CC1;
+sfr __at 0xED T4CC0;
+sfr __at 0xEF T4CC1;
/*
* Peripheral control
*/
-sfr at 0xf1 PERCFG;
+sfr __at 0xf1 PERCFG;
#define PERCFG_T1CFG_ALT_1 (0 << 6)
#define PERCFG_T1CFG_ALT_2 (1 << 6)
#define PERCFG_T1CFG_ALT_MASK (1 << 6)
-teledongle-v0.1
+teledongle-v0.1*
ao_product.h
-PROG = teledongle-v0.1.ihx
+PROG = teledongle-v0.1-$(VERSION).ihx
SRC = \
$(TD_SRC) \
-teledongle-v0.2
+teledongle-v0.2*
ao_product.h
-PROG = teledongle-v0.2.ihx
+PROG = teledongle-v0.2-$(VERSION).ihx
SRC = \
$(TD_SRC) \
-telemetrum-v0.1-sirf
+telemetrum-v0.1-sirf*
ao_product.h
-PROG = telemetrum-v0.1-sirf.ihx
+PROG = telemetrum-v0.1-sirf-$(VERSION).ihx
SRC = \
$(TM_BASE_SRC) \
-telemetrum-v0.1-sky
+telemetrum-v0.1-sky*
ao_product.h
--- /dev/null
+--directory=..
-PROG = telemetrum-v0.1-sky.ihx
+PROG = telemetrum-v0.1-sky-$(VERSION).ihx
SRC = \
$(TM_BASE_SRC) \
-telemetrum-v0.2
+telemetrum-*
ao_product.h
--- /dev/null
+--directory=..
-PROG = telemetrum-v1.0.ihx
+PROG = telemetrum-v1.0-$(VERSION).ihx
SRC = \
$(TM_BASE_SRC) \
-tidongle
+tidongle*
ao_product.h
-PROG = tidongle.ihx
+PROG = tidongle-$(VERSION).ihx
SRC = \
$(TI_SRC)
%Mfg% = Models, NTx86, NTamd64, NTia64\r
\r
[Models.NTx86]\r
-%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A\r
+%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A\r
+%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B\r
+%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C\r
+%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D\r
\r
[Models.NTamd64]\r
%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A\r
+%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B\r
+%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C\r
+%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D\r
\r
[Models.NTia64]\r
%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A\r
+%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B\r
+%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C\r
+%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D\r
\r
[DestinationDirs]\r
DefaultDestDir=12\r
\r
[ControlFlags]\r
ExcludeFromSelect=USB\VID_FFFE&PID_000A\r
+ExcludeFromSelect=USB\VID_FFFE&PID_000B\r
+ExcludeFromSelect=USB\VID_FFFE&PID_000C\r
+ExcludeFromSelect=USB\VID_FFFE&PID_000D\r
\r
[Strings]\r
Mfg = "altusmetrum.org"\r
-TeleMetrum = "TeleMetrum/TeleDongle"\r
+AltusMetrum = "Unknown AltusMetrum Device"\r
+TeleMetrum = "TeleMetrum"\r
+TeleDongle = "TeleDongle"\r
+TeleTerra = "TeleTerra"\r
\r
\r
;----------------------------------------------------------------------------\r